org.eclipse.wst.xml.search.editor.util.JdtUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.wst.xml.search.editor.util.JdtUtils.java

Source

/**
 *  Copyright (c) 2013-2014 Angelo ZERR.
 *  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:
 *  Angelo Zerr <angelo.zerr@gmail.com> - initial API and implementation
 */
package org.eclipse.wst.xml.search.editor.util;

import java.beans.Introspector;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.core.IImportDeclaration;
import org.eclipse.jdt.core.IJarEntryResource;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.internal.core.NamedMember;
import org.eclipse.wst.xml.search.core.queryspecifications.container.IMultiResourceProvider;
import org.eclipse.wst.xml.search.core.util.StringUtils;
import org.eclipse.wst.xml.search.editor.internal.Trace;
import org.eclipse.wst.xml.search.editor.internal.jdt.SuperTypeHierarchyCache;
import org.eclipse.wst.xml.search.editor.searchers.javamethod.requestor.IJavaMethodRequestor;

/**
 * Utility class that provides several helper methods for working with Eclipse's
 * JDT.
 * 
 */
public class JdtUtils {

    public static IType[] EMPTY_TYPE = new IType[0];

    /**
     * 
     * Returns the corresponding Java project or <code>null</code> a for given
     * project.
     * 
     * @param project
     *            the project the Java project is requested for
     * 
     * @return the requested Java project or <code>null</code> if the Java
     *         project is not defined or the project is not
     * 
     *         accessible
     */
    public static IJavaProject getJavaProject(IProject project) {
        if (project.isAccessible())
            try {
                if (project.hasNature(JavaCore.NATURE_ID))
                    return (IJavaProject) project.getNature(JavaCore.NATURE_ID);
            } catch (CoreException e) {
                Trace.trace(Trace.SEVERE, (new StringBuilder("Error getting Java project for project '"))
                        .append(project.getName()).append("'").toString(), e);
            }
        return null;
    }

    public static IFolder getJavaProjectOutputFolder(IProject project) {
        IJavaProject javaProject = getJavaProject(project);
        if (javaProject != null) {
            try {
                return ResourcesPlugin.getWorkspace().getRoot().getFolder(javaProject.getOutputLocation());
            } catch (JavaModelException e) {
                Trace.trace(Trace.SEVERE, (new StringBuilder("Error getting Java project output for project '"))
                        .append(project.getName()).append("'").toString(), e);
            }
        }
        return null;
    }

    public static IResource[] getJavaProjectSrcFolders(IProject project) {
        IJavaProject javaProject = getJavaProject(project);
        if (javaProject != null) {
            try {
                List<IResource> sources = new ArrayList<IResource>();
                IPackageFragmentRoot[] roots = javaProject.getPackageFragmentRoots();
                IPackageFragmentRoot root = null;
                for (int i = 0; i < roots.length; i++) {
                    root = roots[i];
                    if (root.getKind() == IPackageFragmentRoot.K_SOURCE) {
                        sources.add(root.getCorrespondingResource());
                    }
                }
                return sources.toArray(IMultiResourceProvider.EMPTY_RESOURCE);
            } catch (JavaModelException e) {
                Trace.trace(Trace.SEVERE, (new StringBuilder("Error getting Java project src for project '"))
                        .append(project.getName()).append("'").toString(), e);
            }
        }
        return null;
    }

    public static String getPackageName(IContainer container) {
        IJavaProject javaProject = getJavaProject(container.getProject());
        if (javaProject != null) {
            String containerBasePath = container.getFullPath().toString();
            IResource[] srcs = getJavaProjectSrcFolders(container.getProject());
            IResource src = null;
            for (int i = 0; i < srcs.length; i++) {
                src = srcs[i];
                String srcBasePath = src.getFullPath().toString();
                if (containerBasePath.startsWith(srcBasePath)) {
                    String packageName = containerBasePath.substring(srcBasePath.length() + 1,
                            containerBasePath.length());
                    return packageName.replaceAll("/", ".");
                }
            }
            return null;
        }
        return null;
    }

    public static IJarEntryResource getJavaResourceFileFromBinary(IProject project, String jarNamePattern,
            String packageName, String fileName) {
        IJavaProject javaProject = getJavaProject(project);
        if (javaProject != null) {
            try {
                IPackageFragmentRoot[] roots = javaProject.getPackageFragmentRoots();
                IPackageFragmentRoot root = null;
                for (int i = 0; i < roots.length; i++) {
                    root = roots[i];
                    if (root.getKind() == IPackageFragmentRoot.K_BINARY) {
                        if (StringUtils.isEmpty(jarNamePattern)
                                || root.getElementName().startsWith(jarNamePattern)) {
                            Object[] nonJavaResources = null;
                            if (packageName != null) {
                                IPackageFragment fragment = root.getPackageFragment(packageName);
                                if (fragment != null) {
                                    nonJavaResources = fragment.getNonJavaResources();
                                }
                            } else {
                                nonJavaResources = root.getNonJavaResources();
                            }
                            if (nonJavaResources != null) {
                                Object nonJavaResource = null;
                                for (int j = 0; j < nonJavaResources.length; j++) {
                                    nonJavaResource = nonJavaResources[j];
                                    if (nonJavaResource instanceof IJarEntryResource) {
                                        IJarEntryResource r = (IJarEntryResource) nonJavaResource;
                                        if (r.isFile() && fileName.equals(r.getName())) {
                                            return r;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            } catch (JavaModelException e) {
                Trace.trace(Trace.SEVERE, (new StringBuilder("Error getting Java project src for project '"))
                        .append(project.getName()).append("'").toString(), e);
            }
        }
        return null;
    }

    public static IJarEntryResource[] getJavaResourcesFileFromBinary(IProject project, String jarNamePattern,
            String packageName, String fileName) {
        Collection<IJarEntryResource> files = new ArrayList<IJarEntryResource>();
        IJavaProject javaProject = getJavaProject(project);
        if (javaProject != null) {
            try {
                IPackageFragmentRoot[] roots = javaProject.getPackageFragmentRoots();
                IPackageFragmentRoot root = null;
                for (int i = 0; i < roots.length; i++) {
                    root = roots[i];
                    if (root.getKind() == IPackageFragmentRoot.K_BINARY) {
                        if (StringUtils.isEmpty(jarNamePattern) || root.getElementName().contains(jarNamePattern)) {
                            Object[] nonJavaResources = null;
                            if (packageName != null) {
                                IPackageFragment fragment = root.getPackageFragment(packageName);
                                if (fragment != null) {
                                    nonJavaResources = fragment.getNonJavaResources();
                                }
                            } else {
                                nonJavaResources = root.getNonJavaResources();
                            }
                            if (nonJavaResources != null) {
                                Object nonJavaResource = null;
                                for (int j = 0; j < nonJavaResources.length; j++) {
                                    nonJavaResource = nonJavaResources[j];
                                    if (nonJavaResource instanceof IJarEntryResource) {
                                        IJarEntryResource r = (IJarEntryResource) nonJavaResource;
                                        if (r.isFile() && r.getName().contains(fileName)) {
                                            files.add(r);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            } catch (JavaModelException e) {
                Trace.trace(Trace.SEVERE, (new StringBuilder("Error getting Java project src for project '"))
                        .append(project.getName()).append("'").toString(), e);
            }
        }
        return files.toArray(new IJarEntryResource[files.size()]);
    }

    /**
     * 
     * Returns the corresponding Java type for given full-qualified class name.
     * 
     * @param project
     *            the JDT project the class belongs to
     * 
     * @param className
     *            the full qualified class name of the requested Java type
     * 
     * @return the requested Java type or null if the class is not defined or
     *         the project is not accessible
     */

    public static IType getJavaType(IProject project, String className) {
        IJavaProject javaProject = JdtUtils.getJavaProject(project);
        if (className != null) {
            // For inner classes replace '$' by '.'
            int pos = className.lastIndexOf('$');
            if (pos > 0) {
                className = className.replace('$', '.');
            }

            try {
                IType type = null;
                // First look for the type in the Java project
                if (javaProject != null) {
                    // TODO CD not sure why we need
                    type = javaProject.findType(className, new NullProgressMonitor());
                    if (type != null) {
                        return type;
                    }
                }

                // Then look for the type in the referenced Java projects
                for (IProject refProject : project.getReferencedProjects()) {
                    IJavaProject refJavaProject = JdtUtils.getJavaProject(refProject);
                    if (refJavaProject != null) {
                        type = refJavaProject.findType(className);
                        if (type != null) {
                            return type;
                        }
                    }
                }

                // fall back
                return null;
            } catch (CoreException e) {
                Trace.trace(Trace.SEVERE, "Error getting Java type '" + className + "'", e);
            }
        }
        return null;
    }

    public static IType getSuperType(IType type) throws JavaModelException {
        if (type == null)
            return null;
        String name = type.getSuperclassName();
        if (name == null && !type.getFullyQualifiedName().equals(Object.class.getName()))
            name = Object.class.getName();
        if (name != null) {
            if (type.isBinary())
                return type.getJavaProject().findType(name);
            String resolvedName = JdtUtils.resolveClassName(name, type);
            if (resolvedName != null)
                return type.getJavaProject().findType(resolvedName);
        }
        return null;
    }

    public static String resolveClassName(String className, IType type) {

        if (className == null || type == null) {
            return className;
        }

        // replace binary $ inner class name syntax with . for source level
        className = className.replace('$', '.');
        String dotClassName = new StringBuilder().append('.').append(className).toString();
        IProject project = type.getJavaProject().getProject();
        try {
            // Special handling for some well-know classes
            if (className.startsWith("java.lang") && getJavaType(project, className) != null) {
                return className;
            }

            // Check if the class is imported
            if (!type.isBinary()) {
                // Strip className to first segment to support
                // ReflectionUtils.MethodCallback
                int ix = className.lastIndexOf('.');
                String firstClassNameSegment = className;

                if (ix > 0) {
                    firstClassNameSegment = className.substring(0, ix);
                }

                // Iterate the imports
                for (IImportDeclaration importDeclaration : type.getCompilationUnit().getImports()) {
                    String importName = importDeclaration.getElementName();
                    // Wildcard imports -> check if the package + className is a
                    // valid type
                    if (importDeclaration.isOnDemand()) {
                        String newClassName = new StringBuilder(importName.substring(0, importName.length() - 1))
                                .append(className).toString();
                        if (getJavaType(project, newClassName) != null) {
                            return newClassName;

                        }
                    }

                    // Concrete import matching .className at the end -> check
                    // if type exists
                    else if (importName.endsWith(dotClassName) && getJavaType(project, importName) != null) {
                        return importName;
                    }

                    // Check if className is multi segmented
                    // (ReflectionUtils.MethodCallback)
                    // -> check if the first segment
                    else if (!className.equals(firstClassNameSegment)) {
                        if (importName.endsWith(firstClassNameSegment)) {
                            String newClassName = new StringBuilder(
                                    importName.substring(0, importName.lastIndexOf('.') + 1)).append(className)
                                            .toString();

                            if (getJavaType(project, newClassName) != null) {
                                return newClassName;
                            }
                        }
                    }
                }
            }

            // Check if the class is in the same package as the type
            String packageName = type.getPackageFragment().getElementName();
            String newClassName = new StringBuilder(packageName).append(dotClassName).toString();

            if (getJavaType(project, newClassName) != null) {
                return newClassName;
            }

            // Check if the className is sufficient (already fully-qualified)
            if (getJavaType(project, className) != null) {
                return className;
            }

            // Check if the class is coming from the java.lang
            newClassName = new StringBuilder("java.lang").append(dotClassName).toString();
            if (getJavaType(project, newClassName) != null) {
                return newClassName;
            }

            // Fall back to full blown resolution
            String[][] fullInter = type.resolveType(className);
            if (fullInter != null && fullInter.length > 0) {
                return fullInter[0][0] + "." + fullInter[0][1];
            }
        } catch (JavaModelException e) {
            Trace.trace(Trace.SEVERE, "Error resolveClassName'" + className + "'", e);
        }
        return className;

    }

    public static String[] getParameterTypesString(IMethod method) {
        try {
            String parameterQualifiedTypes[] = Signature.getParameterTypes(method.getSignature());
            int length = parameterQualifiedTypes != null ? parameterQualifiedTypes.length : 0;
            String parameterPackages[] = new String[length];
            for (int i = 0; i < length; i++) {
                parameterQualifiedTypes[i] = parameterQualifiedTypes[i].replace('/', '.');
                parameterPackages[i] = Signature.getSignatureSimpleName(parameterQualifiedTypes[i]);
            }

            return parameterPackages;
        } catch (IllegalArgumentException _ex) {
        } catch (JavaModelException _ex) {
        }
        return null;
    }

    public static String getReturnTypeString(IMethod method, boolean classTypesOnly) {
        try {
            String qualifiedReturnType = Signature.getReturnType(method.getSignature());
            if (!classTypesOnly || qualifiedReturnType.startsWith("L") || qualifiedReturnType.startsWith("Q"))
                return Signature.getSignatureSimpleName(qualifiedReturnType.replace('/', '.'));
        } catch (IllegalArgumentException _ex) {
        } catch (JavaModelException _ex) {
        }
        return null;
    }

    public static String getPropertyNameFromMethodName(IMethod method) {
        String methodName = method.getElementName();
        int index = methodName.lastIndexOf('.');
        if (index > 0)
            methodName = methodName.substring(index + 1);
        String replaceText = methodName.substring("set".length());
        if (replaceText != null)
            replaceText = Introspector.decapitalize(replaceText);
        return replaceText;
    }

    public static IMethod findMethod(IType type, String methodNameToFind, IJavaMethodRequestor requestor)
            throws JavaModelException {
        if (type == null) {
            return null;
        }
        IMethod method = null;
        IMethod[] methods = type.getMethods();
        for (int i = 0; i < methods.length; i++) {
            method = methods[i];
            IStatus status = requestor.matchTotally(null, methodNameToFind, method);
            if (status != null && status.isOK()) {
                return method;
            }
        }
        return findMethod(JdtUtils.getSuperType(type), methodNameToFind, requestor);
    }

    public static boolean doesImplement(IResource resource, IType type, IType superType) {
        if (resource == null || type == null || superType == null)
            return false;
        // if(className.startsWith("java.") || className.startsWith("javax."))
        // try
        // {
        // ClassLoader cls = getClassLoader(resource.getProject(), null);
        // Class typeClass = cls.loadClass(type.getFullyQualifiedName('$'));
        // Class interfaceClass = cls.loadClass(className);
        // return typeClass.equals(interfaceClass) ||
        // interfaceClass.isAssignableFrom(typeClass);
        // }
        // catch(Throwable _ex) { }
        return doesImplementWithJdt(resource, type, superType);
    }

    private static boolean doesImplementWithJdt(IResource resource, IType type, IType interfaceType) {
        // IType interfaceType = getJavaType(resource.getProject(), className);
        // if (interfaceType == null) {
        // return false;
        // }
        IType subTypes[];
        try {
            subTypes = SuperTypeHierarchyCache.getTypeHierarchy(interfaceType).getAllSubtypes(interfaceType);
            if (subTypes != null) {
                for (IType subType : subTypes) {
                    if (subType.equals(type)) {
                        return true;
                    }
                }
            }
        } catch (JavaModelException e) {
            Trace.trace(Trace.SEVERE, "Error doesImplementWithJdt", e);
        }
        return false;

    }

    public static IType[] getImplementsType(IType type) {
        try {
            return SuperTypeHierarchyCache.getTypeHierarchy(type).getAllClasses();
        } catch (JavaModelException e) {
            return null;
        }
    }

    public static boolean isImplementsClass(final IJavaElement javaElement, final String className)
            throws JavaModelException {
        Assert.isNotNull(javaElement);
        if (javaElement != null && javaElement instanceof NamedMember) {
            final NamedMember method = (NamedMember) javaElement;
            final IType type = method.getDeclaringType();
            if (type != null) {
                if (type.getFullyQualifiedName().equals(className)) {
                    return true;
                }
                return hierarchyContainsComponent(type, className);
            }
        }
        return false;
    }

    public static boolean hierarchyContainsComponent(final IType type, final String className)
            throws JavaModelException {
        Assert.isNotNull(type);
        final ITypeHierarchy hierarchy = type.newSupertypeHierarchy(null);
        if (hierarchy != null) {
            final IType[] supertypes = hierarchy.getAllSupertypes(type);
            for (final IType iType : supertypes) {
                if (iType.getFullyQualifiedName().equals(className)) {
                    return true;
                }
            }
        }
        return false;
    }
}