Package org.springframework.ide.eclipse.core.io

Source Code of org.springframework.ide.eclipse.core.io.EclipsePathMatchingResourcePatternResolver

/*******************************************************************************
* Copyright (c) 2008, 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.io;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IStorage;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJarEntryResource;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.UrlResource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.ide.eclipse.core.java.JdtUtils;
import org.springframework.util.ClassUtils;

/**
* Eclipse specific {@link ResourceLoader} implementation that understands the same rules applied by
* {@link PathMatchingResourcePatternResolver} of Spring.
* <p>
* See the later for a comprehensive description of the supported patterns and semantics.
* @author Christian Dupuis
* @author Martin Lippert
* @since 2.0.3
* @see PathMatchingResourcePatternResolver
*/
public class EclipsePathMatchingResourcePatternResolver implements ResourcePatternResolver {

  private final PathMatchingResourcePatternResolver patternResolver;

  private final IProject project;

  private final ResourceLoader resourceLoader;

  private final Map<String, Resource[]> resolvedResources = new ConcurrentHashMap<String, Resource[]>();

  private IJavaProject javaProject;
  private IPackageFragmentRoot[] roots;

  public EclipsePathMatchingResourcePatternResolver(IProject project) {
    this(project, JdtUtils.getClassLoader(project, null));
  }

  public EclipsePathMatchingResourcePatternResolver(IProject project, ClassLoader classLoader) {
    this.resourceLoader = new EclipseFileResourceLoader(this, classLoader);
    this.project = project;
    this.patternResolver = new PathMatchingResourcePatternResolver(classLoader);
  }

  /**
   * Return the ClassLoader that this pattern resolver works with (never <code>null</code>).
   */
  public ClassLoader getClassLoader() {
    return getResourceLoader().getClassLoader();
  }

  public Resource getResource(String location) {
    // long start = System.currentTimeMillis();
    try {

      // Check cache first
      if (resolvedResources.containsKey(location)) {
        return resolvedResources.get(location)[0];
      }

      Resource resource = patternResolver.getResource(location);
      if (resource != null) {
        try {
          // initialize and cache javaProject and package fragment roots
          // because they are expensive at runtime
          if (javaProject == null || roots == null) {
            javaProject = JdtUtils.getJavaProject(project);
            roots = javaProject.getAllPackageFragmentRoots();
          }
         
          Resource newResource = processRawResource(roots, resource);
          if (newResource != null) {
            resource = newResource;
          }
          else {
            System.out.println(String.format("!-- could not resolve '%s'", resource));
          }
        }
        catch (JavaModelException e) {
        }
        catch (IOException e) {
        }
      }

      resolvedResources.put(location, new Resource[] { resource });
      return resource;
    }
    finally {
      // System.out.println(String.format("--- resolving location '%s' took '%s'ms", location, (System
      // .currentTimeMillis() - start)));
    }
  }

  /**
   * Return the ResourceLoader that this pattern resolver works with.
   */
  public ResourceLoader getResourceLoader() {
    return this.resourceLoader;
  }

  public Resource[] getResources(String locationPattern) throws IOException {
    // long start = System.currentTimeMillis();
    try {

      // Check cache first
      if (resolvedResources.containsKey(locationPattern)) {
        return resolvedResources.get(locationPattern);
      }

      Resource[] resources = patternResolver.getResources(locationPattern);
      Set<Resource> foundResources = new HashSet<Resource>();

      try {
        // initialize and cache javaProject and package fragment roots
        // because they are expensive at runtime
        if (javaProject == null || roots == null) {
          javaProject = JdtUtils.getJavaProject(project);
          roots = javaProject.getAllPackageFragmentRoots();
        }

        for (Resource resource : resources) {
          Resource newResource = processRawResource(roots, resource);
          if (newResource != null) {
            foundResources.add(newResource);
          }
          else {
            System.out.println(String.format("!-- could not resolve '%s'", resource));
          }
        }
      }
      catch (JavaModelException e) {
        // The implementation is called too often to log
      }

      Resource[] result = foundResources.toArray(new Resource[foundResources.size()]);
      resolvedResources.put(locationPattern, result);

      return result;
    }
    finally {
      // System.out.println(String.format("--- resolving resource pattern '%s' took '%s'ms", locationPattern,
      // (System.currentTimeMillis() - start)));
    }
  }

  /**
   * Verify if the <code>resources</code> array contains a file matching <code>fileName</code>.
   */
  private IStorage contains(Object[] resources, String fileName) {
    for (Object resource : resources) {
      if (resource instanceof IResource) {
        if (((IResource) resource).getName().equals(fileName)) {
          return (IStorage) resource;
        }
      }
      else if (resource instanceof IJarEntryResource) {
        if (((IJarEntryResource) resource).getName().equals(fileName)) {
          return (IStorage) resource;
        }
      }
    }
    return null;
  }

  private Resource processClassResource(String path, String fileName, String typeName, IPackageFragmentRoot root,
      IJavaElement[] children) throws JavaModelException {
    for (IJavaElement je : children) {
      if (je instanceof ICompilationUnit) {
        for (IType type : ((ICompilationUnit) je).getAllTypes()) {
          if (type.getFullyQualifiedName('$').equals(typeName)) {
            if (root.getRawClasspathEntry().getEntryKind() == IClasspathEntry.CPE_SOURCE) {

              IPath outputLocation = root.getRawClasspathEntry().getOutputLocation();
              if (outputLocation == null) {
                outputLocation = root.getJavaProject().getOutputLocation();
              }
              IResource classResource = ResourcesPlugin.getWorkspace().getRoot().findMember(
                  outputLocation.append(path));
              if (classResource != null) {
                return new FileResource((IFile) classResource);
              }
            }
          }
        }
      }
      else if (je instanceof IClassFile) {
        if (((IClassFile) je).getElementName().equals(fileName)) {
          // Workspace jar or resource
          if (root.getResource() != null) {
            return new StorageResource(new ZipEntryStorage((IFile) root.getResource(), path), project);
          }
          // Workspace external jar
          else {
            File jarFile = root.getPath().toFile();
            return new ExternalFile(jarFile, path, project);
          }
        }
      }
    }
    return null;
  }

  private Resource processRawResource(IPackageFragmentRoot[] roots, Resource resource) throws IOException,
      JavaModelException {
    if (resource instanceof FileSystemResource) {
      // This can only be something in the Eclipse workspace
     
      // first check the location in the project that this pattern resolver is associated with (most likely path)
      Path path = new Path(((FileSystemResource) resource).getPath());
      IPath projectLocation = this.project.getLocation();
      if (projectLocation.isPrefixOf(path)) {
        int segmentsToRemove = projectLocation.segmentCount();
        IPath projectRelativePath = path.removeFirstSegments(segmentsToRemove);
        IFile file = this.project.getFile(projectRelativePath);
        if (file != null && file.exists()) {
          return new FileResource(file);
        }
      }

      // then check the simple getFileForLocation (faster in case it is not a linked resource)
      IFile fileForLocation = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(path);
      if (fileForLocation != null) {
        return new FileResource(fileForLocation);
      }

      // fall back to full resolution via findFilesForLocationURI
      IResource[] allResourcesFor = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(resource.getURI());
      for (IResource res : allResourcesFor) {
        return new FileResource((IFile) res);
      }
    }
    else if (resource instanceof UrlResource) {
      URL url = resource.getURL();
      String path = url.getPath();
      int ix = path.indexOf('!');
      if (ix > 0) {
        String entryName = path.substring(ix + 1);
        path = path.substring(0, ix);

        try {
          return new ExternalFile(new File(new URI(path)), entryName, project);
        }
        catch (URISyntaxException e) {
        }
      }
      else {
        IResource[] allResourcesFor = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(
            resource.getURI());
        for (IResource res : allResourcesFor) {
          return new FileResource((IFile) res);
        }
      }
    }
    else if (resource instanceof ClassPathResource) {
      String path = ((ClassPathResource) resource).getPath();
      String fileName = path;
      String packageName = "";
      int ix = path.lastIndexOf('/');
      if (ix > 0) {
        fileName = path.substring(ix + 1);
        packageName = path.substring(0, ix).replace('/', '.');
      }
      if (fileName.endsWith(ClassUtils.CLASS_FILE_SUFFIX)) {
        String typeName = packageName + "." + fileName.substring(0, fileName.length() - 6);
        for (IPackageFragmentRoot root : roots) {
          Resource storage = null;

          if ("".equals(packageName) && root.exists()) {
            storage = processClassResource(path, fileName, typeName, root, root.getChildren());
          }

          IPackageFragment packageFragment = root.getPackageFragment(packageName);
          if (storage == null && packageFragment != null && packageFragment.exists()) {
            storage = processClassResource(path, fileName, typeName, root, packageFragment.getChildren());
          }

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

      else {
        for (IPackageFragmentRoot root : roots) {
          IStorage storage = null;

          // Look in the root of the package fragment root
          if ("".equals(packageName) && root.exists()) {
            storage = contains(root.getNonJavaResources(), fileName);
          }

          // Check the package
          IPackageFragment packageFragment = root.getPackageFragment(packageName);
          if (storage == null && packageFragment != null && packageFragment.exists()) {
            storage = contains(packageFragment.getNonJavaResources(), fileName);
          }
         
          // Check the root folder in case no package exists
          if (storage == null) {
            IResource rootResource = root.getUnderlyingResource();
            if (rootResource instanceof IFolder) {
              IFile file = ((IFolder) rootResource).getFile(path);
              if (file.exists()) {
                storage = file;
              }
            }
          }

          // Found the resource in the package fragment root? -> construct usable Resource
          if (storage != null) {
            if (storage instanceof IFile) {
              return new FileResource((IFile) storage);
            }
            else if (storage instanceof IJarEntryResource) {

              // Workspace jar or resource
              if (root.getResource() != null) {
                return new StorageResource(new ZipEntryStorage((IFile) root.getResource(),
                    ((IJarEntryResource) storage).getFullPath().toString()), project);
              }
              // Workspace external jar
              else {
                File jarFile = root.getPath().toFile();
                return new ExternalFile(jarFile,
                    ((IJarEntryResource) storage).getFullPath().toString(), project);
              }
            }
          }
        }
      }
    }
    return null;
  }

}
TOP

Related Classes of org.springframework.ide.eclipse.core.io.EclipsePathMatchingResourcePatternResolver

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.