Package org.springframework.ide.eclipse.core.java

Source Code of org.springframework.ide.eclipse.core.java.JdtUtils$DefaultProjectClassLoaderSupport

/*******************************************************************************
* Copyright (c) 2007, 2014 Spring IDE Developers
* 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:
*     Spring IDE Developers - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.core.java;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IImportDeclaration;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaModel;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeParameter;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.ASTVisitor;
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.SearchMatch;
import org.eclipse.jdt.core.search.SearchParticipant;
import org.eclipse.jdt.core.search.SearchPattern;
import org.eclipse.jdt.core.search.SearchRequestor;
import org.eclipse.jdt.launching.JavaRuntime;
import org.osgi.framework.Bundle;
import org.springframework.ide.eclipse.core.SpringCore;
import org.springframework.ide.eclipse.core.java.Introspector.Public;
import org.springframework.ide.eclipse.core.java.Introspector.Static;
import org.springframework.ide.eclipse.core.java.typehierarchy.TypeHierarchyEngine;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
import org.springsource.ide.eclipse.commons.core.SpringCoreUtils;
import org.springsource.ide.eclipse.commons.core.StatusHandler;

/**
* Utility class that provides several helper methods for working with Eclipse's JDT.
* @author Christian Dupuis
* @author Martin Lippert
* @author Leo Dos Santos
* @since 2.0
*/
public class JdtUtils {

  public static final String CLASS_FILE_EXTENSION = ".class";

  public static final String GROOVY_FILE_EXTENSION = ".groovy";

  public static final String JAVA_FILE_EXTENSION = ".java";

  private static final String AJDT_CLASS = "org.eclipse.ajdt.core.javaelements.AJCompilationUnitManager";

  private static final String AJDT_NATURE = "org.eclipse.ajdt.ui.ajnature";

  private static final String CLASSPATH_FILENAME = ".classpath";

  private static final boolean IS_AJDT_PRESENT = isAjdtPresent();

  /**
   * Creates specified Java project.
   */
  public static IJavaProject createJavaProject(String projectName, IProgressMonitor monitor) throws CoreException {
    IProject project = SpringCoreUtils.createProject(projectName, null, monitor);
    if (monitor.isCanceled()) {
      throw new OperationCanceledException();
    }
    if (!project.hasNature(JavaCore.NATURE_ID)) {
      SpringCoreUtils.addProjectNature(project, JavaCore.NATURE_ID, monitor);
    }
    IJavaProject jproject = JavaCore.create(project);
    // append JRE entry
    jproject.setRawClasspath(new IClasspathEntry[] { getJreVariableEntry() }, monitor);
    jproject.setOutputLocation(project.getFullPath(), monitor);
    if (monitor.isCanceled()) {
      throw new OperationCanceledException();
    }
    return jproject;
  }

  /**
   * Checks if the given <code>type</code> implements/extends <code>className</code>.
   */
  public static boolean doesImplement(IResource resource, IType type, String className) {
    return doesImplement(resource, type, className, SpringCore.getTypeHierarchyEngine());
  }

  /**
   * Checks if the given <code>type</code> implements/extends <code>className</code>.
   */
  public static boolean doesImplement(IResource resource, IType type, String className, TypeHierarchyEngine typeEngine) {
    if (resource == null || type == null || className == 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 e) {
        // ignore this and fall back to JDT does implement checks
      }
    }
   
    if (System.getProperty(TypeHierarchyEngine.ENABLE_PROPERTY, "true").equals("true")) {
      return typeEngine.doesImplement(type, className) || typeEngine.doesExtend(type, className);
    }
    else {
      return doesImplementWithJdt(resource, type, className);
    }
  }

  public static IType getAjdtType(IProject project, String className) {
    IJavaProject javaProject = getJavaProject(project);
    if (IS_AJDT_PRESENT && javaProject != null && className != null) {

      try {
        IType type = null;

        // First look for the type in the project
        if (isAjdtProject(project)) {
          type = AjdtUtils.getAjdtType(project, className);
          if (type != null) {
            return type;
          }
        }

        // Then look for the type in the referenced Java projects
        for (IProject refProject : project.getReferencedProjects()) {
          if (isAjdtProject(refProject)) {
            type = AjdtUtils.getAjdtType(refProject, className);
            if (type != null) {
              return type;
            }
          }
        }
      }
      catch (CoreException e) {
        SpringCore.log("Error getting Java type '" + className + "'", e);
      }
    }
    return null;
  }

  public static List<IJavaProject> getAllDependingJavaProjects(IJavaProject project) {
    List<IJavaProject> javaProjects = new ArrayList<IJavaProject>();
    IJavaModel model = JavaCore.create(ResourcesPlugin.getWorkspace().getRoot());
    if (model != null) {
      try {
        String[] names = project.getRequiredProjectNames();
        IJavaProject[] projects = model.getJavaProjects();
        for (int index = 0; index < projects.length; index++) {
          for (int offset = 0; offset < names.length; offset++) {
            String name = projects[index].getProject().getName();
            if (name.equals(names[offset])) {
              javaProjects.add(projects[index]);
            }
          }
        }
      }
      catch (JavaModelException exception) {
      }
    }
    return javaProjects;
  }

  /**
   * Creates a Set of {@link URL}s from the OSGi bundle class path manifest entry.
   */
  public static Set<URL> getBundleClassPath(String bundleId) {
    Set<URL> paths = new HashSet<URL>();
    try {
      Bundle bundle = Platform.getBundle(bundleId);
      if (bundle != null) {
        String bundleClassPath = (String) bundle.getHeaders()
            .get(org.osgi.framework.Constants.BUNDLE_CLASSPATH);
        if (bundleClassPath != null) {
          String[] classPathEntries = StringUtils.delimitedListToStringArray(bundleClassPath, ",");
          for (String classPathEntry : classPathEntries) {
            if (".".equals(classPathEntry.trim())) {
              paths.add(FileLocator.toFileURL(bundle.getEntry("/")));
            }
            else {
              try {
                paths.add(FileLocator.toFileURL(new URL(bundle.getEntry("/"), "/" + classPathEntry.trim())));
              }
              catch (FileNotFoundException e) {
                SpringCore.log("bundle classpath entry \"" + classPathEntry.trim() + "\" of bundle " + bundle.getSymbolicName() + " not found and therefore ignored", e);
              }
            }
          }
        }
        else {
          paths.add(FileLocator.toFileURL(bundle.getEntry("/")));
        }
      }
    }
    catch (MalformedURLException e) {
      SpringCore.log(e);
    }
    catch (IOException e) {
      SpringCore.log(e);
    }
    return paths;
  }
 
  /**
   * @since 2.6.0
   */
  public static IJavaElement getByHandle(String handle) {
    if (IS_AJDT_PRESENT) {
      return AjdtUtils.getByHandle(handle);
    }
    else {
      return JavaCore.create(handle);
    }
  }

  /**
   * Create a {@link ClassLoader} from the class path configuration of the given <code>project</code>.
   * @param project the {@link IProject}
   * @param useParentClassLoader true if the current OSGi class loader should be used as parent class loader for the
   * constructed class loader.
   * @return {@link ClassLoader} instance constructed from the <code>project</code>'s build path configuration
   */
  public static ClassLoader getClassLoader(IProject project, ClassLoader parentClassLoader) {
    return ProjectClassLoaderCache.getClassLoader(project, parentClassLoader);
  }
 
  public static void removeClassLoaderEntryFromCache(IProject project) {
    ProjectClassLoaderCache.removeClassLoaderEntryFromCache(project);
  }


  public static IMethod getConstructor(IType type, Class[] parameterTypes) {
    String[] parameterTypesAsString = getParameterTypesAsStringArray(parameterTypes);
    return getConstructor(type, parameterTypesAsString);
  }

  public static IMethod getConstructor(IType type, String[] parameterTypes) {
    try {
      Set<IMethod> methods = Introspector.getAllConstructors(type);
      for (IMethod method : methods) {
        if (method.getParameterTypes().length == parameterTypes.length) {
          String[] methodParameterTypes = getParameterTypesAsStringArray(method);
          if (Arrays.deepEquals(parameterTypes, methodParameterTypes)) {
            return method;
          }
        }
      }
    }
    catch (JavaModelException e) {
    }
    return null;
  }

  public static IField getField(IType type, String fieldName) {
    return getField(type, fieldName, true);
  }

  /**
   * @since 3.2.0
   */
  public static IField getField(IType type, String fieldName, boolean includeHierarchy) {
    try {
      while (type != null) {
        for (IField field : type.getFields()) {
          if (field.getElementName().equals(fieldName)) {
            return field;
          }
        }
        if (!includeHierarchy) break;
        type = Introspector.getSuperType(type);
      }
    }
    catch (JavaModelException e) {
    }
    return null;
  }

  /**
   * Returns a flat list of all interfaces and super types for the given {@link IType}.
   */
  public static List<String> getFlatListOfClassAndInterfaceNames(IType parameterType, IType type) {
    List<String> requiredTypes = new ArrayList<String>();
    if (parameterType != null) {
      do {
        try {
          requiredTypes.add(parameterType.getFullyQualifiedName());
          String[] interfaceNames = parameterType.getSuperInterfaceNames();
          for (String interfaceName : interfaceNames) {
            if (interfaceName != null) {
              if (type.isBinary()) {
                requiredTypes.add(interfaceName);
              }
              String resolvedName = resolveClassName(interfaceName, type);
              if (resolvedName != null) {
                requiredTypes.add(resolvedName);
              }
            }
          }
          parameterType = Introspector.getSuperType(parameterType);
        }
        catch (JavaModelException e) {
        }
      } while (parameterType != null && !parameterType.getFullyQualifiedName().equals(Object.class.getName()));
    }
    return requiredTypes;
  }

  /**
   * 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) {
        SpringCore.log("Error getting Java project for project '" + project.getName() + "'", e);
      }
    }
    return null;
  }

  public static IJavaProject getJavaProject(IResource config) {
    IJavaProject project = JavaCore.create(config.getProject());
    return project;
  }

  /**
   * 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 '.'
      String unchangedClassName = null;
      int pos = className.lastIndexOf('$');
      if (pos > 0) {
        unchangedClassName = className;
        className = className.replace('$', '.');
      }

      try {
        IType type = null;
        // First look for the type in the Java project
        if (javaProject != null) {
          type = javaProject.findType(className, new NullProgressMonitor());
         
          if (type == null && unchangedClassName != null) {
            type = findTypeWithInnerClassesInvolved(javaProject, unchangedClassName, 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 && unchangedClassName != null) {
              type = findTypeWithInnerClassesInvolved(javaProject, unchangedClassName, new NullProgressMonitor());
            }

            if (type != null) {
              return type;
            }
          }
        }

        // fall back and try to locate the class using AJDT
        return getAjdtType(project, className);
      }
      catch (CoreException e) {
        SpringCore.log("Error getting Java type '" + className + "'", e);
      }
    }

    return null;
  }

  protected static IType findTypeWithInnerClassesInvolved(IJavaProject javaProject, String fullClassName, NullProgressMonitor progressMonitor) throws JavaModelException {
    IType result = javaProject.findType(fullClassName, progressMonitor);
/*   
    if (result == null || !result.exists()) {
      String mainClassName = fullClassName.substring(0, fullClassName.indexOf('$'));
      IType mainClass = javaProject.findType(mainClassName, progressMonitor);
     
      if (mainClass != null && mainClass.exists() && !mainClass.isBinary()) {
        IType outerClass = mainClass;
       
        String innerClasses = fullClassName.substring(fullClassName.indexOf('$') + 1);
        StringTokenizer innerClassTokens = new StringTokenizer(innerClasses, "$");
        while (innerClassTokens.hasMoreTokens()) {
          String innerClass = innerClassTokens.nextToken();

          try {
            int anonymousInnerClassNo = Integer.parseInt(innerClass);
            outerClass = outerClass.getType("", anonymousInnerClassNo);
          }
          catch (NumberFormatException e) {
            outerClass = outerClass.getType(innerClass);
          }
        };
       
        result = outerClass;
      }
    }
*/
    return result;
  }

  public static final IType getJavaTypeForMethodReturnType(IMethod method, IType contextType) {
    try {
      return JdtUtils.getJavaTypeFromSignatureClassName(method.getReturnType(), contextType);
    }
    catch (JavaModelException e) {
    }
    return null;
  }

  public static IType getJavaTypeFromSignatureClassName(String className, IType contextType) {
    if (contextType == null || className == null) {
      return null;
    }
    try {
      return JdtUtils.getJavaType(contextType.getJavaProject().getProject(), JdtUtils
          .resolveClassNameBySignature(className, contextType));
    }
    catch (IllegalArgumentException e) {
      // do Nothing
    }
    return null;
  }

  public static final List<IType> getJavaTypesForMethodParameterTypes(IMethod method, IType contextType) {
    if (method == null || method.getParameterTypes() == null || method.getParameterTypes().length == 0) {
      return Collections.EMPTY_LIST;
    }
    List<IType> parameterTypes = new ArrayList<IType>(method.getParameterTypes().length);
    String[] parameterTypeNames = method.getParameterTypes();
    for (String parameterTypeName : parameterTypeNames) {
      parameterTypes.add(JdtUtils.getJavaTypeFromSignatureClassName(parameterTypeName, contextType));
    }
    return parameterTypes;
  }

  public static IClasspathEntry getJreVariableEntry() {
    return JavaRuntime.getDefaultJREContainerEntry();
  }

  public static int getLineNumber(IJavaElement element) {
    if (element != null && element instanceof IMethod) {
      try {
        IMethod method = (IMethod) element;
        int lines = 0;
        if (method.getDeclaringType() != null && method.getDeclaringType().getCompilationUnit() != null) {
          String targetsource = method.getDeclaringType().getCompilationUnit().getSource();
          if (targetsource != null) {
            String sourceuptomethod = targetsource.substring(0, method.getNameRange().getOffset());

            char[] chars = new char[sourceuptomethod.length()];
            sourceuptomethod.getChars(0, sourceuptomethod.length(), chars, 0);
            for (char element0 : chars) {
              if (element0 == '\n') {
                lines++;
              }
            }
            return new Integer(lines + 1);
          }
        }
      }
      catch (JavaModelException e) {
      }
    }
    else if (element != null && element instanceof IType && ((IType) element).getCompilationUnit() != null) {
      try {
        IType type = (IType) element;
        int lines = 0;
        String targetsource = type.getCompilationUnit().getSource();
        if (targetsource != null) {
          String sourceuptomethod = targetsource.substring(0, type.getNameRange().getOffset());

          char[] chars = new char[sourceuptomethod.length()];
          sourceuptomethod.getChars(0, sourceuptomethod.length(), chars, 0);
          for (char element0 : chars) {
            if (element0 == '\n') {
              lines++;
            }
          }
          return new Integer(lines + 1);
        }
      }
      catch (JavaModelException e) {
      }
    }
    else if (element != null && element instanceof IField) {
      try {
        IField type = (IField) element;
        int lines = 0;
        ICompilationUnit cu = type.getCompilationUnit();
        if (cu != null) {
          String targetsource = cu.getSource();
          if (targetsource != null) {
            String sourceuptomethod = targetsource.substring(0, type.getNameRange().getOffset());
 
            char[] chars = new char[sourceuptomethod.length()];
            sourceuptomethod.getChars(0, sourceuptomethod.length(), chars, 0);
            for (char element0 : chars) {
              if (element0 == '\n') {
                lines++;
              }
            }
            return new Integer(lines + 1);
          }
        }
      }
      catch (JavaModelException e) {
      }
    }
    return new Integer(-1);
  }

  public static IMethod getMethod(IType type, String methodName, Class[] parameterTypes) {
    String[] parameterTypesAsString = getParameterTypesAsStringArray(parameterTypes);
    return getMethod(type, methodName, parameterTypesAsString);
  }

  public static IMethod getMethod(IType type, String methodName, String[] parameterTypes) {
    return getMethod(type, methodName, parameterTypes, true);
  }

  /**
   * @since 3.2.0
   */
  public static IMethod getMethod(IType type, String methodName, String[] parameterTypes, boolean includeHierarchy) {
    int index = methodName.indexOf('(');
    if (index >= 0) {
      methodName = methodName.substring(0, index);
    }
    try {
      while (type != null) {
        for (IMethod method : Introspector.getMethods(type)) {
          if (method.getElementName().equals(methodName)
              && method.getParameterTypes().length == parameterTypes.length) {
            String[] methodParameterTypes = getParameterTypesAsStringArray(method);
            if (Arrays.deepEquals(parameterTypes, methodParameterTypes)) {
              return method;
            }
          }
        }
        if (!includeHierarchy) break;
        type = Introspector.getSuperType(type);
      }

      return Introspector.findMethod(type, methodName, parameterTypes.length, Public.YES, Static.DONT_CARE);
    }
    catch (JavaModelException e) {
    }
    return null;
  }

  public static String getMethodName(IMethod method) {
    // Special support Ajdt intertype declarations
    String methodName = method.getElementName();
    int index = methodName.lastIndexOf('.');
    if (index > 0) {
      methodName = methodName.substring(index + 1);
    }
    return methodName;
  }

  public static String[] getParameterTypesString(IMethod method) {
    try {
      String[] parameterQualifiedTypes = Signature.getParameterTypes(method.getSignature());
      int length = parameterQualifiedTypes == null ? 0 : parameterQualifiedTypes.length;
      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 e) {
    }
    catch (JavaModelException e) {
    }
    return null;
  }

  public static String getParentName(IMethod method) {
    // Special support Ajdt intertype declarations
    String methodName = method.getElementName();
    int index = methodName.lastIndexOf('.');
    if (index > 0) {
      return methodName.substring(0, index);
    }
    else {
      return method.getParent().getElementName();
    }
  }

  public static IProjectClassLoaderSupport getProjectClassLoaderSupport(IProject je, ClassLoader parentClassLoader) {
    return new DefaultProjectClassLoaderSupport(je, parentClassLoader);
  }

  public static String getPropertyNameFromMethodName(IMethod method) {
    // Special support Ajdt intertype declarations
    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 = java.beans.Introspector.decapitalize(replaceText);
    }
    return replaceText;
  }

  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 e) {
    }
    catch (JavaModelException e) {
    }
    return null;
  }

  public static IResource getSourceResource(IResource classFile) {
    try {
      if (isJavaProject(classFile) && classFile.getName().endsWith(CLASS_FILE_EXTENSION)) {
        IPath classFilePath = classFile.getFullPath();
        String classFileName = null;

        IJavaProject project = getJavaProject(classFile);
        IPath defaultOutput = project.getOutputLocation();

        if (defaultOutput.isPrefixOf(classFilePath)) {
          classFileName = classFilePath.removeFirstSegments(defaultOutput.segmentCount()).toString();
        }
        else {
          for (IClasspathEntry entry : project.getRawClasspath()) {
            if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
              IPath output = entry.getOutputLocation();
              if (output != null) {
                if (classFilePath.isPrefixOf(output)) {
                  classFileName = classFilePath.removeFirstSegments(output.segmentCount()).toString();
                }
              }
            }
          }
        }

        if (classFileName != null) {
          // Replace file extension
          String sourceFileName = classFileName.replace(".class", ".java");
          for (IClasspathEntry entry : project.getRawClasspath()) {
            if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
              IPath path = entry.getPath().append(sourceFileName).removeFirstSegments(1);
              IResource resource = project.getProject().findMember(path);
              if (resource != null) {
                return resource;
              }
            }
          }
        }
      }
    }
    catch (JavaModelException e) {
    }
    return null;
  }

  public static boolean isAjdtPresent() {
      return Platform.getBundle("org.eclipse.ajdt.core") != null;
  }

  /**
   * Returns true if given resource's project is a ADJT project.
   */
  public static boolean isAjdtProject(IResource resource) {
    if (resource != null && resource.isAccessible()) {
      IProject project = resource.getProject();
      if (project != null) {
        try {
          return project.hasNature(AJDT_NATURE);
        }
        catch (CoreException e) {
          SpringCore.log(e);
        }
      }
    }
    return false;
  }

  /**
   * Determines if the <code>resource</code> under question is the .classpath file of a {@link IJavaProject}.
   */
  public static boolean isClassPathFile(IResource resource) {
    String classPathFileName = resource.getProject().getFullPath().append(CLASSPATH_FILENAME).toString();
    return resource.getFullPath().toString().equals(classPathFileName);
  }
 
  /**
   * Returns true if given resource's project is a Java project.
   */
  public static boolean isJavaProject(IResource resource) {
    if (resource != null && resource.isAccessible()) {
      IProject project = resource.getProject();
      if (project != null) {
        try {
          return project.hasNature(JavaCore.NATURE_ID);
        }
        catch (CoreException e) {
          SpringCore.log(e);
        }
      }
    }
    return false;
  }

  public static boolean isTypeAjdtElement(IType type) {
    if (IS_AJDT_PRESENT) {
      return AjdtUtils.isTypeAjdtElement(type);
    }
    return false;
  }

  public static boolean isTypeGroovyElement(IType type) {
    // TODO CD verify following check with Groovy Eclipse
    ICompilationUnit cu = type.getCompilationUnit();
    if (cu != null && cu.getResource() != null) {
      return cu.getResource().getName().endsWith(GROOVY_FILE_EXTENSION);
    }
    else if (cu != null) {
      try {
        IResource resource = cu.getUnderlyingResource();
        if (resource != null) {
          return resource.getName().endsWith(GROOVY_FILE_EXTENSION);
        }
      }
      catch (JavaModelException e) {
        // ignore
      }
    }
    return false;
  }

  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) {
      SpringCore.log(e);
    }

    return className;
  }

  public static String resolveClassNameBySignature(String className, IType type) {
    // in case the type is already resolved
    if (className != null && className.length() > 0 && className.charAt(0) == Signature.C_RESOLVED) {
      return Signature.toString(className).replace('$', '.');
    }
    // otherwise do the resolving
    else {
      className = Signature.toString(className).replace('$', '.');
      return resolveClassName(className, type);
    }
  }

  public static void visitTypeAst(IType type, ASTVisitor visitor) {
    if (type != null && type.getCompilationUnit() != null) {
      ASTParser parser = ASTParser.newParser(AST.JLS3);
      parser.setSource(type.getCompilationUnit());
      parser.setResolveBindings(true);
      ASTNode node = parser.createAST(new NullProgressMonitor());
      node.accept(visitor);
    }
  }

  private static boolean doesImplementWithJdt(IResource resource, IType type, String className) {
    IType interfaceType = getJavaType(resource.getProject(), className);
    if (type != null && interfaceType != null) {
      try {
        IType[] subTypes = SuperTypeHierarchyCache.getTypeHierarchy(interfaceType)
            .getAllSubtypes(interfaceType);
        if (subTypes != null) {
          for (IType subType : subTypes) {
            if (subType.equals(type)) {
              return true;
            }
          }
        }
      }
      catch (JavaModelException ex) {
        SpringCore.log(ex);
      }
    }
    return false;
  }

  private static String[] getParameterTypesAsStringArray(Class[] parameterTypes) {
    String[] parameterTypesAsString = new String[parameterTypes.length];
    for (int i = 0; i < parameterTypes.length; i++) {
      parameterTypesAsString[i] = ClassUtils.getQualifiedName(parameterTypes[i]);
    }
    return parameterTypesAsString;
  }

  private static String[] getParameterTypesAsStringArray(IMethod method) {
    Set<String> typeParameterNames = new HashSet<String>();
    try {
      for (ITypeParameter param : method.getDeclaringType().getTypeParameters()) {
        typeParameterNames.add(param.getElementName());
      }
      for (ITypeParameter param : method.getTypeParameters()) {
        typeParameterNames.add(param.getElementName());
      }
    }
    catch (JavaModelException e) {
    }
    String[] parameterTypesAsString = new String[method.getParameterTypes().length];
    for (int i = 0; i < method.getParameterTypes().length; i++) {
      String parameterTypeString = Signature.getElementType(method.getParameterTypes()[i]);
      boolean isArray = !parameterTypeString.equals(method.getParameterTypes()[i]);

      String parameterType = resolveClassNameBySignature(parameterTypeString, method.getDeclaringType());
      if (typeParameterNames.contains(parameterType)) {
        parameterTypesAsString[i] = Object.class.getName() + (isArray ? ClassUtils.ARRAY_SUFFIX : "");
      }
      else {
        parameterTypesAsString[i] = parameterType + (isArray ? ClassUtils.ARRAY_SUFFIX : "");
      }
    }
    return parameterTypesAsString;
  }

  static class DefaultProjectClassLoaderSupport implements IProjectClassLoaderSupport {

    private ClassLoader classLoader;

    private ClassLoader weavingClassLoader;

    public DefaultProjectClassLoaderSupport(IProject javaProject, ClassLoader parentClassLoader) {
      setupClassLoaders(javaProject, parentClassLoader);
    }

    public void executeCallback(IProjectClassLoaderAwareCallback callback) throws Throwable {
      try {
        activateWeavingClassLoader();
        callback.doWithActiveProjectClassLoader();
      }
      finally {
        recoverClassLoader();
      }
    }

    public ClassLoader getProjectClassLoader() {
      return this.weavingClassLoader;
    }

    /**
     * Activates the weaving class loader as thread context classloader.
     * <p>
     * Use {@link #recoverClassLoader()} to recover the original thread context classloader
     */
    private void activateWeavingClassLoader() {
      Thread.currentThread().setContextClassLoader(weavingClassLoader);
    }

    private void recoverClassLoader() {
      Thread.currentThread().setContextClassLoader(classLoader);
    }

    private void setupClassLoaders(IProject project, ClassLoader parentClassLoader) {
      classLoader = Thread.currentThread().getContextClassLoader();
      weavingClassLoader = ProjectClassLoaderCache.getClassLoader(project, parentClassLoader);
    }
  }
 
  public static Set<IType> searchForJavaConfigs(SearchPattern pattern, IJavaSearchScope scope) {
    final Set<IType> annotatedTypes = new HashSet<IType>();
    SearchRequestor requestor = new SearchRequestor() {
      @Override
      public void acceptSearchMatch(SearchMatch match) throws CoreException {
        if (match.getAccuracy() == SearchMatch.A_ACCURATE && !match.isInsideDocComment()) {
          Object element = match.getElement();
          if (element instanceof IType) {
            annotatedTypes.add((IType) element);
          } else if (element instanceof IMethod) {
            IType type = ((IMethod) element).getDeclaringType();
            if (type != null) {
              annotatedTypes.add(type);
            }
          }
        }
      }
    };

    try {
      new SearchEngine().search(pattern, new SearchParticipant[] { SearchEngine.getDefaultSearchParticipant() },
          scope, requestor, null);
    } catch (CoreException e) {
      StatusHandler.log(new Status(IStatus.ERROR, SpringCore.PLUGIN_ID,
          "An error occurred while searching for Java config files.", e));
    }
    return annotatedTypes;
  }
 
  public static Set<IType> searchForJavaConfigs(IJavaSearchScope scope) {
    SearchPattern configurationPattern = SearchPattern.createPattern("org.springframework.context.annotation.Configuration",
        IJavaSearchConstants.ANNOTATION_TYPE, IJavaSearchConstants.ANNOTATION_TYPE_REFERENCE,
        SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE);
    SearchPattern componentPattern = SearchPattern.createPattern( "org.springframework.stereotype.Component",
        IJavaSearchConstants.ANNOTATION_TYPE, IJavaSearchConstants.ANNOTATION_TYPE_REFERENCE,
        SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE);
    SearchPattern beanPattern = SearchPattern.createPattern("org.springframework.context.annotation.Bean",
        IJavaSearchConstants.ANNOTATION_TYPE, IJavaSearchConstants.ANNOTATION_TYPE_REFERENCE,
        SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE);
    SearchPattern importPattern = SearchPattern.createPattern("org.springframework.context.annotation.Import",
        IJavaSearchConstants.ANNOTATION_TYPE, IJavaSearchConstants.ANNOTATION_TYPE_REFERENCE,
        SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE);
    SearchPattern bootAutoConfigPattern = SearchPattern.createPattern("org.springframework.boot.autoconfigure.EnableAutoConfiguration",
        IJavaSearchConstants.ANNOTATION_TYPE, IJavaSearchConstants.ANNOTATION_TYPE_REFERENCE,
        SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE);

    SearchPattern pattern = SearchPattern.createOrPattern(configurationPattern, componentPattern);
    pattern = SearchPattern.createOrPattern(pattern, beanPattern);
    pattern = SearchPattern.createOrPattern(pattern, importPattern);
    pattern = SearchPattern.createOrPattern(pattern, bootAutoConfigPattern);
    return searchForJavaConfigs(pattern, scope);
  }


}
TOP

Related Classes of org.springframework.ide.eclipse.core.java.JdtUtils$DefaultProjectClassLoaderSupport

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.