br.jabuti.lookup.java.bytecode.RClassCode.java Source code

Java tutorial

Introduction

Here is the source code for br.jabuti.lookup.java.bytecode.RClassCode.java

Source

/*  Copyright 2003  Auri Marcelo Rizzo Vicenzi, Marcio Eduardo Delamaro,              Jose Carlos Maldonado
    
This file is part of Jabuti.
    
Jabuti is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as 
published by the Free Software Foundation, either version 3 of the      
License, or (at your option) any later version.
    
Jabuti is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
    
You should have received a copy of the GNU Lesser General Public License
along with Jabuti.  If not, see <http://www.gnu.org/licenses/>.
*/

package br.jabuti.lookup.java.bytecode;

import org.aspectj.apache.bcel.classfile.*;
import org.aspectj.apache.bcel.generic.ConstantPoolGen;
import org.aspectj.apache.bcel.generic.Instruction;
import org.aspectj.apache.bcel.generic.InstructionHandle;
import org.aspectj.apache.bcel.generic.InstructionList;
import org.aspectj.apache.bcel.generic.InvokeInstruction;
import org.aspectj.apache.bcel.generic.MethodGen;

import java.io.*;
import java.util.Vector;

import br.jabuti.util.Persistency;

/**
 <p>This class is used to store information about a given class
 in a program. A program is represented by {@link Program} object.
 A {@link RClassCode} object extends {@link RClass} and so
 it stores information about which subclasses
 extends the class and which classes implements it (if it is 
 an interface).<BR>
 In addition, it stores complete information about the class 
 itself. For that it uses a {@link org.aspectj.apache.bcel.classfile.JavaClass}
 object
 </p>
    
 <p>This class is used in the context of a program to represent those 
 classes that are in the scope of interest. For example, if 
 the program is built over a set of 5 classes <BR>
    
 <UL>
 <LI> MyClass1
 <LI> MyClass2
 <LI> MyClass3
 <LI> MyClass4
 <LI> MyClassFive
 </UL> <BR>
    
 these classes are represented using this {@link RClassCode} class and
 the relationship about them (subclassing and implementation) are also
 registered.
 </p>
    
 @version 0.00001
 @author Marcio Delamaro
 @see RClass
 @see Program
    
 */
public class RClassCode extends RClass {

    /** Stores the complete information about the class */
    private JavaClass theClass; // non persistent
    private String theClassPersistent; // persistent

    /* Guarda algumas informacoes sobre a classe: */

    /** Stores the superclass name */
    private String superName;

    /** Is an interface ? */
    private boolean isInter;

    /** List of impleented interfaces */
    private String[] interfaces;

    /** Creates a RClassCode given its name and a {@link JavaClass}
     object 
        
     @param y The {@link JavaClass} object already created for this class
     @param x The complete name of the class
     */
    public RClassCode(JavaClass y, String x) {
        super(x);
        theClass = null;
        theClassPersistent = Persistency.add(y.getBytes());
        if (theClassPersistent == null)
            theClass = y;
        superName = y.getSuperclassName();
        interfaces = y.getInterfaceNames();
        isInter = y.isInterface();
    }

    /** Return the name of the superclass. The name is extracted from
     the {@link RClassCode#theClass} field.
        
     @return The complete name of its superclass
     */
    public String getSuperClass() {
        return superName;
    }

    /** Return the list of interfaces this class implements. 
     The names are extracted from
     the {@link RClassCode#theClass} field.
        
     @return The complete names of its interfaces
     */
    public String[] getInterfaces() {
        return interfaces;
    }

    /** Return whether this class is an interface. The
     information is extracted from
     the {@link RClassCode#theClass} field.
        
     @return True if this is an interface
     */
    public boolean isInterface() {
        return isInter;
    }

    /** Return the {@link JavaClass} object that represents this class
        
     @return the {@link JavaClass} object that represents this class
     */
    public JavaClass getTheClass() {
        if (theClass != null)
            return theClass;
        try {
            byte[] b = (byte[]) Persistency.get(theClassPersistent);
            ByteArrayInputStream bais = new ByteArrayInputStream(b);
            JavaClass javaClass = new ClassParser(bais, null).parse();
            bais.close();
            return javaClass;
        } catch (Exception e) {
            return null;
        }
    }

    /** Retorna uma lista de metodos chamados por um dado metodo
     * desta classe.
     * @param assinatura - a assinatura do metodo que se deseja analisar
     * @return a lista de metodos chamados pelo metodo passado como argumento.
     * Se o metodo solicitado nao for encontrado na classe, retorna null.
     */
    public String[] getCalledMethods(String assinatura) {
        JavaClass jc = this.getTheClass();
        Method[] mv = jc.getMethods();
        Method m = null;
        String met = new String();
        int i;
        for (i = 0; i < mv.length; i++) {
            m = mv[i];

            met = jc.getClassName() + "." + mv[i].getName() + mv[i].getSignature();
            System.out.println("Metodo Aplicao = " + met);
            System.out.println("Metodo Parametro = " + assinatura);

            if (met.equals(assinatura))
                break;
        }
        if (i == mv.length)
            return null;
        ConstantPoolGen cp = new ConstantPoolGen(jc.getConstantPool());
        MethodGen mg = new MethodGen(m, jc.getClassName(), cp);

        InstructionList il = mg.getInstructionList();
        InstructionHandle[] ih = il.getInstructionHandles();
        Vector v = new Vector();

        for (int x = 0; x < ih.length; x++) {
            Instruction ins = ih[x].getInstruction();
            if (ins instanceof InvokeInstruction) {
                InvokeInstruction invoke = (InvokeInstruction) ins;
                String s = invoke.getClassName(cp) + "." + invoke.getMethodName(cp) + invoke.getSignature(cp);

                //System.out.println("gettype = " + invoke.getClassType(cp));
                System.out.println("metodo retornado = " + s);
                v.add(s);
            }
        }
        return (String[]) v.toArray(new String[0]);
    }

    /**
     Send a few information to the standard output like <BR>
     <UL>
     <LI> Interface or class
     <LI> The name 
     <LI> The superclass
     <LI> The interfaces it implements
     <LI> Its subclasses
     <LI> Its implementations
     </UL>
        
     */
    public void print() {
        System.out.println();
        String s = isInterface() ? "Interface" : "Class";

        System.out.println("******* Code " + s + " " + getName() + " *********");
        System.out.println("Extends: " + getSuperClass());
        String[] subs = getInterfaces();

        System.out.println("Implements: ");
        for (int i = 0; i < subs.length; i++) {
            System.out.println(subs[i] + " ");
        }

        subs = getSubClasses();
        System.out.println("Extended by: ");
        for (int i = 0; i < subs.length; i++) {
            System.out.println(subs[i] + " ");
        }

        subs = getImplementations();
        System.out.println("Implemented by: ");
        for (int i = 0; i < subs.length; i++) {
            System.out.println(subs[i] + " ");
        }
    }

}