tod.plugin.TODPluginUtils.java Source code

Java tutorial

Introduction

Here is the source code for tod.plugin.TODPluginUtils.java

Source

/*
TOD plugin - Eclipse pluging for TOD
Copyright (C) 2006 Guillaume Pothier (gpothier@dcc.uchile.cl)
    
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
    
This program 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 General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    
Parts of this work rely on the MD5 algorithm "derived from the 
RSA Data Security, Inc. MD5 Message-Digest Algorithm".
*/
package tod.plugin;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IInitializer;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaModel;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeParameter;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.core.search.SearchParticipant;
import org.eclipse.jdt.core.search.SearchPattern;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.internal.Workbench;

import tod.Util;
import tod.core.database.browser.ILogBrowser;
import tod.core.database.structure.IClassInfo;
import tod.core.database.structure.ILocationInfo;
import tod.core.database.structure.IStructureDatabase;
import tod.core.database.structure.ITypeInfo;
import tod.core.session.ISession;
import tod.plugin.views.main.MainView;
import tod.utils.ConfigUtils;
import tod.utils.TODUtils;
import zz.utils.ArrayStack;
import zz.utils.KeySorter;
import zz.utils.Stack;
import zz.utils.Utils;
import zz.utils.KeySorter.KeyProvider;

/**
 * Utilities for the TOD plugin
 * @author gpothier
 */
public class TODPluginUtils {
    /**
     * Returns the TOD location info that corresponds to the given element in the
     * given session.
     * @param aSession The debugging session in which the element should be looked for
     * @param aElement The JDT java element to look for.
     * @return TOD location info, or null if none is found.
     */
    public static ILocationInfo getLocationInfo(ISession aSession, IJavaElement aElement)
            throws JavaModelException {
        if (aSession == null)
            TODUtils.log(0, "Trying to show event while no session is available.");
        ILogBrowser theLogBrowser = aSession.getLogBrowser();
        IStructureDatabase theStructureDatabase = theLogBrowser.getStructureDatabase();

        if (aElement instanceof IMember) {
            IMember theMember = (IMember) aElement;

            IType theType = theMember.getDeclaringType();
            if (theType == null)
                return null;

            String theTypeName = theType.getFullyQualifiedName();
            IClassInfo theClass = theStructureDatabase.getClass(theTypeName, false);
            if (theClass == null)
                return null;

            TODUtils.logf(0, "Trying to show events for class %s of id %s", theClass.getName(), theClass.getId());

            if (theMember instanceof IMethod) {
                IMethod theMethod = (IMethod) theMember;
                String theMethodName = theMethod.getElementName();
                ITypeInfo[] theArgumentTypes = getArgumentTypes(theStructureDatabase, theMethod.getParameterTypes(),
                        theType);

                ITypeInfo theReturnType = getReturnType(theStructureDatabase, theMethod.getReturnType(), theType);

                if (theMethodName.equals(Util.getSimpleInnermostName(theTypeName))) {
                    theMethodName = "<init>";

                    // Include synthetic parameters for inner classes constructors
                    IType theCurrentType = theType;
                    List<ITypeInfo> theSyntheticArgs = new ArrayList<ITypeInfo>();
                    while (theCurrentType != null) {
                        IType theDeclaringType = theCurrentType.getDeclaringType();
                        if (theDeclaringType != null) {
                            // This is an inner class
                            if (!Flags.isStatic(theCurrentType.getFlags())) {
                                IClassInfo theInnerClass = theStructureDatabase
                                        .getClass(theDeclaringType.getFullyQualifiedName(), false);

                                theSyntheticArgs.add(theInnerClass);
                            }
                        }
                        theCurrentType = theDeclaringType;
                    }

                    if (theSyntheticArgs.size() > 0) {
                        Utils.fillCollection(theSyntheticArgs, theArgumentTypes);
                        theArgumentTypes = theSyntheticArgs.toArray(new ITypeInfo[theSyntheticArgs.size()]);
                    }
                }

                return theClass.getBehavior(theMethodName, theArgumentTypes, theReturnType);
            } else if (theMember instanceof IInitializer) {
                IInitializer theInitializer = (IInitializer) theMember;
                String theInitializerName = theInitializer.getElementName();
                return theClass.getBehavior(theInitializerName, null, null);
            } else if (theMember instanceof IField) {
                IField theField = (IField) theMember;
                String theFieldName = theField.getElementName();
                return theClass.getField(theFieldName);
            }
        }

        return null;
    }

    public static ITypeInfo[] getArgumentTypes(IStructureDatabase aStructureDatabase, String[] aJDTSignatures,
            IType aDeclaringType) throws JavaModelException {
        int theCount = aJDTSignatures.length;
        ITypeInfo[] theTypes = new ITypeInfo[theCount];

        for (int i = 0; i < theCount; i++) {
            theTypes[i] = getType(aStructureDatabase, aJDTSignatures[i], aDeclaringType);
            if (theTypes[i] == null)
                return null;
        }

        return theTypes;
    }

    public static ITypeInfo getReturnType(IStructureDatabase aStructureDatabase, String aJDTSignature,
            IType aDeclaringType) throws JavaModelException {
        return getType(aStructureDatabase, aJDTSignature, aDeclaringType);
    }

    public static ITypeInfo getType(IStructureDatabase aStructureDatabase, String aJDTSignature,
            IType aDeclaringType) throws JavaModelException {
        String theTypeName = getResolvedTypeName(aJDTSignature, aDeclaringType);
        return theTypeName != null ? aStructureDatabase.getType(theTypeName, true) : null;
    }

    /**
     * Returns the resolved Java type signature that corresponds 
     * to a JDT type signature as defined in {@link Signature}.
     * Inspired from {@link JavaModelUtil#getResolvedTypeName(String, IType)}.
     */
    public static String getResolvedTypeName(String aJDTSignature, IType aDeclaringType) throws JavaModelException {
        int theArrayDepth = Signature.getArrayCount(aJDTSignature);
        String theBaseSignature = aJDTSignature.substring(theArrayDepth);
        String theBaseName = getResolvedTypeName0(theBaseSignature, aDeclaringType);
        StringBuilder theName = new StringBuilder();
        for (int i = 0; i < theArrayDepth; i++)
            theName.append('[');
        theName.append(theBaseName);

        return theName.toString();
    }

    private static String getResolvedTypeName0(String aBaseJDTSignature, IType aDeclaringType)
            throws JavaModelException {
        char type = aBaseJDTSignature.charAt(0);

        if (type == Signature.C_UNRESOLVED) {
            String name = ""; //$NON-NLS-1$
            int bracket = aBaseJDTSignature.indexOf(Signature.C_GENERIC_START, 1);
            if (bracket > 0)
                name = aBaseJDTSignature.substring(1, bracket);
            else {
                int semi = aBaseJDTSignature.indexOf(Signature.C_SEMICOLON, 1);
                if (semi == -1) {
                    throw new IllegalArgumentException();
                }
                name = aBaseJDTSignature.substring(1, semi);
            }

            String[][] resolvedNames = aDeclaringType.resolveType(name);
            if (resolvedNames != null && resolvedNames.length > 0) {
                StringBuilder theBuilder = new StringBuilder();
                theBuilder.append(Signature.C_RESOLVED);
                String thePackage = resolvedNames[0][0];
                String theClass = resolvedNames[0][1].replace('.', '$');
                if (thePackage != null) {
                    theBuilder.append(thePackage);
                    theBuilder.append('.');
                }
                theBuilder.append(theClass);
                theBuilder.append(Signature.C_SEMICOLON);
                return theBuilder.toString();
            }

            ITypeParameter theTypeParameter = aDeclaringType.getTypeParameter(name);
            if (theTypeParameter != null) {
                String[] theBounds = theTypeParameter.getBounds();
                if (theBounds != null && theBounds.length > 0) {
                    System.out.println(Arrays.asList(theBounds));
                }
                return "Ljava/lang/Object;";
            }

            return null;
        } else {
            return aBaseJDTSignature;
        }
    }

    private static final SearchParticipant[] PARTICIPANTS = { SearchEngine.getDefaultSearchParticipant() };

    /**
     * Searches for declarations of the given name and kind in the whole workspace. 
     */
    public static List searchDeclarations(List<IJavaProject> aJavaProject, String aName, int aKind)
            throws CoreException {
        // Recursively add referenced projects (because Eclipse doesn't recursively include non-exported referenced projects) 
        Set<IJavaProject> theProjects = new HashSet<IJavaProject>();
        Stack<IJavaProject> theWorkingList = new ArrayStack<IJavaProject>();
        for (IJavaProject theProject : aJavaProject)
            theWorkingList.push(theProject);

        while (!theWorkingList.isEmpty()) {
            IJavaProject theProject = theWorkingList.pop();
            theProjects.add(theProject);

            IJavaModel theJavaModel = theProject.getJavaModel();
            IClasspathEntry[] theEntries = theProject.getResolvedClasspath(true);
            for (IClasspathEntry theEntry : theEntries)
                if (theEntry.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
                    IJavaProject theReferencedProject = theJavaModel
                            .getJavaProject(theEntry.getPath().lastSegment());
                    if (theReferencedProject.exists() && !theProjects.contains(theReferencedProject))
                        theWorkingList.push(theReferencedProject);
                }
        }

        SearchPattern thePattern = SearchPattern.createPattern(aName.replace('$', '.'), aKind,
                IJavaSearchConstants.DECLARATIONS, SearchPattern.R_EXACT_MATCH);

        IJavaSearchScope theScope = SearchEngine
                .createJavaSearchScope(theProjects.toArray(new IJavaElement[theProjects.size()]), true);

        SearchEngine theSearchEngine = new SearchEngine();
        SimpleResultCollector theCollector = new SimpleResultCollector();

        theSearchEngine.search(thePattern, PARTICIPANTS, theScope, theCollector, null);

        return theCollector.getResults();
    }

    public static IType getType(List<IJavaProject> aJavaProject, String aTypeName) throws CoreException {
        // Search Java type
        List<IType> theList = searchDeclarations(aJavaProject, aTypeName, IJavaSearchConstants.TYPE);

        if (theList.isEmpty())
            return null;

        theList = KeySorter.sort(theList, new KeySorter.KeyProvider<Integer, IType>() {
            public Integer getKey(IType aType) {
                return aType.isBinary() ? 0 : 1;
            }
        });

        return theList.get(theList.size() - 1);
    }

    /**
     * Find and optionally gives focus to the trace navigator view.
     */
    public static MainView getMainView(final boolean aShow) {
        final MainView[] theResult = new MainView[1];
        Runnable theRunnable = new Runnable() {
            public void run() {
                try {
                    String theViewId = ConfigUtils.readString("tod.plugin-view", MainView.VIEW_ID);

                    IWorkbenchWindow theWindow = Workbench.getInstance().getActiveWorkbenchWindow();
                    IWorkbenchPage thePage = theWindow.getActivePage();

                    MainView theView = (MainView) (aShow ? thePage.showView(theViewId)
                            : thePage.findView(theViewId));

                    theResult[0] = theView;
                } catch (PartInitException e) {
                    throw new RuntimeException(e);
                }
            }
        };

        if (Display.getDefault().getThread() == Thread.currentThread())
            theRunnable.run();
        else
            Display.getDefault().syncExec(theRunnable);

        return theResult[0];
    }

    //   public static void gotoSource (IJavaProject aJavaProject, String aTypeName, final int aLineNumber)
    //   {
    //      try
    //      {
    //         IType theType = getType(aJavaProject, aTypeName);
    //         if (theType == null) return;
    //
    //         final ICompilationUnit theCompilationUnit = theType.getCompilationUnit();
    //         
    //         Display.getDefault().asyncExec(new Runnable ()
    //         {
    //            public void run()
    //            {
    //               try
    //               {
    //                  IEditorPart theEditorPart = JavaUI.openInEditor(theCompilationUnit);
    //
    //                  // Select precise line
    //                  if (theEditorPart instanceof ITextEditor && aLineNumber >= 0)
    //                  {
    //                     ITextEditor theEditor = (ITextEditor) theEditorPart;
    //                     
    //                     IDocumentProvider provider = theEditor.getDocumentProvider();
    //                     IDocument document = provider.getDocument(theEditor.getEditorInput());
    //                     int start = document.getLineOffset(aLineNumber-1);
    //                     theEditor.selectAndReveal(start, 0);
    //                     
    //                  }
    //               } 
    //               catch (Exception e)
    //               {
    //                  e.printStackTrace();
    //               }
    //            }
    //         });
    //      }
    //      catch (CoreException e)
    //      {
    //         e.printStackTrace();
    //      }
    //   }
    //   
}