org.eclipse.xtext.ui.util.JdtClasspathUriResolver.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.xtext.ui.util.JdtClasspathUriResolver.java

Source

/*******************************************************************************
 * Copyright (c) 2008 itemis AG (http://www.itemis.eu) and others.
 * 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
 *******************************************************************************/
package org.eclipse.xtext.ui.util;

import static org.eclipse.xtext.util.Strings.*;

import java.util.Set;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.common.util.URI;
import org.eclipse.jdt.core.IClasspathEntry;
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.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.core.ExternalPackageFragmentRoot;
import org.eclipse.xtext.resource.ClasspathUriResolutionException;
import org.eclipse.xtext.resource.ClasspathUriUtil;
import org.eclipse.xtext.resource.IClasspathUriResolver;

import com.google.common.collect.Sets;

public class JdtClasspathUriResolver implements IClasspathUriResolver {

    private IJavaElement javaElement;

    @Override
    public URI resolve(Object context, URI classpathUri) {
        if (!(context instanceof IJavaElement)) {
            throw new IllegalArgumentException("Context must implement IResource");
        }
        javaElement = (IJavaElement) context;
        try {
            if (ClasspathUriUtil.isClasspathUri(classpathUri)) {
                IJavaProject javaProject = javaElement.getJavaProject();
                URI result = findResourceInWorkspace(javaProject, classpathUri);
                if (classpathUri.fragment() != null)
                    result = result.appendFragment(classpathUri.fragment());
                return result;
            }
        } catch (Exception exc) {
            throw new ClasspathUriResolutionException(exc);
        }
        return classpathUri;
    }

    protected URI findResourceInWorkspace(IJavaProject javaProject, URI classpathUri) throws CoreException {
        if (javaProject.exists()) {
            String packagePath = classpathUri.trimSegments(1).path();
            String fullPath = classpathUri.path();
            String fileName = classpathUri.lastSegment();
            IPath filePath = new Path(fileName);
            String packageName = isEmpty(packagePath) ? "" : packagePath.substring(1).replace('/', '.');
            for (IPackageFragmentRoot packageFragmentRoot : javaProject.getAllPackageFragmentRoots()) {
                IPackageFragment packageFragment = packageFragmentRoot.getPackageFragment(packageName);
                if (packageFragment.exists()) {
                    IResource packageFragmentResource = packageFragment.getResource();
                    if (packageFragmentResource instanceof IContainer) {
                        IFile file = ((IContainer) packageFragmentResource).getFile(filePath);
                        if (file.exists())
                            return createPlatformResourceURI(file);
                    } else { // jar file or external class folder
                        if (packageFragmentRoot.isArchive()) { // jar file
                            Object[] nonJavaResources = getNonJavaResources(packageFragmentRoot, packageFragment);
                            for (Object nonJavaResource : nonJavaResources) {
                                IJarEntryResource jarEntryResource = (IJarEntryResource) nonJavaResource;
                                if (fullPath.equals(jarEntryResource.getFullPath().toString())) {
                                    IResource packageFragmentRootResource = packageFragmentRoot.getResource();
                                    if (packageFragmentRootResource != null) { // we have a resource - use nested platform/resource
                                        URI packageFragmentRootURI = createPlatformResourceURI(
                                                packageFragmentRootResource);
                                        URI result = createArchiveURI(packageFragmentRootURI, fullPath);
                                        return result;
                                    } else {
                                        // no resource - use file uri
                                        IPath packageFragmentRootPath = packageFragmentRoot.getPath();
                                        URI packageFragmentRootURI = URI
                                                .createFileURI(packageFragmentRootPath.toString());
                                        URI result = createArchiveURI(packageFragmentRootURI, fullPath);
                                        return result;
                                    }
                                }
                            }
                        } else if (packageFragmentRoot.isExternal()) { // external class folder
                            Object[] nonJavaResources = getNonJavaResources(packageFragmentRoot, packageFragment);
                            for (Object nonJavaResource : nonJavaResources) {
                                IJarEntryResource jarEntryResource = (IJarEntryResource) nonJavaResource;
                                if (fileName.equals(jarEntryResource.getName())) {
                                    IResource packageFragmentRootResource = ((ExternalPackageFragmentRoot) packageFragmentRoot)
                                            .resource();
                                    IPath absolutePath = packageFragmentRootResource.getFullPath();
                                    absolutePath = absolutePath.append(fullPath);
                                    return createPlatformResourceURI(absolutePath);
                                }
                            }
                        }
                    }
                }
            }
            // not found in a source folder - look for a resource relative to project root
            // of this project or one of its dependencies
            URI result = findResourceInProjectRoot(javaProject, classpathUri.path(), Sets.<String>newHashSet());
            if (result != null) {
                return result;
            }
        }
        return classpathUri;
    }

    private URI findResourceInProjectRoot(IJavaProject javaProject, String path, Set<String> visited)
            throws CoreException {
        boolean includeAll = visited.isEmpty();
        if (visited.add(javaProject.getElementName())) {
            IProject project = javaProject.getProject();
            IResource resourceFromProjectRoot = project.findMember(path);
            if (resourceFromProjectRoot != null && resourceFromProjectRoot.exists()) {
                return createPlatformResourceURI(resourceFromProjectRoot);
            }
            for (IClasspathEntry entry : javaProject.getResolvedClasspath(true)) {
                if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
                    if (includeAll || entry.isExported()) {
                        IResource referencedProject = project.getWorkspace().getRoot().findMember(entry.getPath());
                        if (referencedProject != null && referencedProject.getType() == IResource.PROJECT) {
                            IJavaProject referencedJavaProject = JavaCore.create((IProject) referencedProject);
                            if (referencedJavaProject.exists()) {
                                URI result = findResourceInProjectRoot(referencedJavaProject, path, visited);
                                if (result != null) {
                                    return result;
                                }
                            }
                        }
                        break;
                    }
                }
            }
        }
        return null;
    }

    private Object[] getNonJavaResources(IPackageFragmentRoot packageFragmentRoot, IPackageFragment packageFragment)
            throws JavaModelException {
        Object[] nonJavaResources = null;
        if (packageFragment.isDefaultPackage()) {
            nonJavaResources = packageFragmentRoot.getNonJavaResources();
        } else {
            nonJavaResources = packageFragment.getNonJavaResources();
        }
        return nonJavaResources;
    }

    protected URI createArchiveURI(URI baseURI, String entryPath) {
        URI result = URI.createURI("archive:" + baseURI.toString() + "!" + entryPath);
        return result;
    }

    protected URI createPlatformResourceURI(IResource resource) {
        IPath resourcePath = resource.getFullPath();
        return createPlatformResourceURI(resourcePath);
    }

    private URI createPlatformResourceURI(IPath resourcePath) {
        URI result = URI.createPlatformResourceURI(resourcePath.toString(), true);
        return result;
    }

}