org.eclipse.jst.j2ee.internal.dialogs.TypeJavaSearchScope.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.jst.j2ee.internal.dialogs.TypeJavaSearchScope.java

Source

/*******************************************************************************
 * Copyright (c) 2003, 2005 IBM Corporation 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
 *
 * Contributors:
 * IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jst.j2ee.internal.dialogs;

import java.util.ArrayList;
import java.util.HashSet;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IClasspathEntry;
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.IOpenable;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.search.IJavaSearchScope;

/**
 * This class was derived from JavaSearchScope as that class did not have a
 * provision to exclude classpath entries that are not exported A Java-specific
 * scope for searching relative to one or more java elements.
 */
public class TypeJavaSearchScope implements IJavaSearchScope {

    private boolean includeExportedClassPathEntriesOnly = true;

    private ArrayList elements;

    /*
     * The paths of the resources in this search scope (or the classpath
     * entries' paths if the resources are projects)
     */
    private IPath[] paths;
    private boolean[] pathWithSubFolders;
    private int pathsCount;

    private IPath[] enclosingProjectsAndJars;

    public TypeJavaSearchScope() {
        this.initialize();

        // disabled for now as this could be expensive
        // JavaModelManager.getJavaModelManager().rememberScope(this);
    }

    private void addEnclosingProjectOrJar(IPath path) {
        int length = this.enclosingProjectsAndJars.length;
        for (int i = 0; i < length; i++) {
            if (this.enclosingProjectsAndJars[i].equals(path))
                return;
        }
        System.arraycopy(this.enclosingProjectsAndJars, 0, this.enclosingProjectsAndJars = new IPath[length + 1], 0,
                length);
        this.enclosingProjectsAndJars[length] = path;
    }

    /**
     * Method addProject. This method adds all the classpath entries for the
     * current project to the search scope.
     * 
     * @param javaProject
     * @param includesPrereqProjects
     * @param visitedProjects
     * @throws JavaModelException
     */
    public void addProject(IJavaProject javaProject, boolean includesPrereqProjects, HashSet visitedProjects)
            throws JavaModelException {
        IProject project = javaProject.getProject();
        if (!project.isAccessible() || !visitedProjects.add(project))
            return;

        this.addEnclosingProjectOrJar(project.getFullPath());

        IClasspathEntry[] entries = javaProject.getResolvedClasspath(true);
        IJavaModel model = javaProject.getJavaModel();
        for (int i = 0, length = entries.length; i < length; i++) {
            IClasspathEntry entry = entries[i];
            switch (entry.getEntryKind()) {
            case IClasspathEntry.CPE_LIBRARY:
                IPath path = entry.getPath();
                this.add(path, true);
                this.addEnclosingProjectOrJar(path);
                break;
            case IClasspathEntry.CPE_PROJECT:
                if (includesPrereqProjects) {
                    this.add(model.getJavaProject(entry.getPath().lastSegment()), true, visitedProjects);
                }
                break;
            case IClasspathEntry.CPE_SOURCE:
                this.add(entry.getPath(), true);
                break;
            }
        }
    }

    /**
     * Method add. This method filters out all the classpath entries of the
     * project which are not exported.
     * 
     * @param javaProject
     * @param includesPrereqProjects
     * @param visitedProjects
     * @throws JavaModelException
     */
    public void add(IJavaProject javaProject, boolean includesPrereqProjects, HashSet visitedProjects)
            throws JavaModelException {
        IProject project = javaProject.getProject();
        if (!project.isAccessible() || !visitedProjects.add(project))
            return;

        this.addEnclosingProjectOrJar(project.getFullPath());

        IClasspathEntry[] entries = javaProject.getResolvedClasspath(true);
        IJavaModel model = javaProject.getJavaModel();
        for (int i = 0, length = entries.length; i < length; i++) {
            IClasspathEntry entry = entries[i];
            if (includeExportedClassPathEntriesOnly()) {
                if (!entry.isExported() && entry.getEntryKind() != IClasspathEntry.CPE_SOURCE)
                    continue;
            }
            switch (entry.getEntryKind()) {
            case IClasspathEntry.CPE_LIBRARY:
                IPath path = entry.getPath();
                this.add(path, true);
                this.addEnclosingProjectOrJar(path);
                break;
            case IClasspathEntry.CPE_PROJECT:
                if (includesPrereqProjects) {
                    this.add(model.getJavaProject(entry.getPath().lastSegment()), true, visitedProjects);
                }
                break;
            case IClasspathEntry.CPE_SOURCE:
                this.add(entry.getPath(), true);
                break;
            }
        }
    }

    public void add(IJavaElement element) throws JavaModelException {
        IPackageFragmentRoot root = null;
        switch (element.getElementType()) {
        case IJavaElement.JAVA_MODEL:
            // a workspace sope should be used
            break;
        case IJavaElement.JAVA_PROJECT:
            this.add((IJavaProject) element, true, new HashSet(2));
            break;
        case IJavaElement.PACKAGE_FRAGMENT_ROOT:
            root = (IPackageFragmentRoot) element;
            this.add(root.getPath(), true);
            break;
        case IJavaElement.PACKAGE_FRAGMENT:
            root = (IPackageFragmentRoot) element.getParent();
            if (root.isArchive()) {
                this.add(root.getPath().append(new Path(element.getElementName().replace('.', '/'))), false);
            } else {
                IResource resource = element.getUnderlyingResource();
                if (resource != null && resource.isAccessible()) {
                    this.add(resource.getFullPath(), false);
                }
            }
            break;
        default:
            // remember sub-cu (or sub-class file) java elements
            if (element instanceof IMember) {
                if (this.elements == null) {
                    this.elements = new ArrayList();
                }
                this.elements.add(element);
            }
            this.add(this.fullPath(element), true);

            // find package fragment root including this java element
            IJavaElement parent = element.getParent();
            while (parent != null && !(parent instanceof IPackageFragmentRoot)) {
                parent = parent.getParent();
            }
            if (parent instanceof IPackageFragmentRoot) {
                root = (IPackageFragmentRoot) parent;
            }
        }

        if (root != null) {
            if (root.getKind() == IPackageFragmentRoot.K_BINARY) {
                this.addEnclosingProjectOrJar(root.getPath());
            } else {
                this.addEnclosingProjectOrJar(root.getJavaProject().getProject().getFullPath());
            }
        }
    }

    /**
     * Adds the given path to this search scope. Remember if subfolders need to
     * be included as well.
     */
    private void add(IPath path, boolean withSubFolders) {
        if (this.paths.length == this.pathsCount) {
            System.arraycopy(this.paths, 0, this.paths = new IPath[this.pathsCount * 2], 0, this.pathsCount);
            System.arraycopy(this.pathWithSubFolders, 0, this.pathWithSubFolders = new boolean[this.pathsCount * 2],
                    0, this.pathsCount);
        }
        this.paths[this.pathsCount] = path;
        this.pathWithSubFolders[this.pathsCount++] = withSubFolders;
    }

    /*
     * (non-Javadoc)
     * 
     * @see IJavaSearchScope#encloses(String)
     */
    public boolean encloses(String resourcePathString) {
        IPath resourcePath;
        int separatorIndex = resourcePathString.indexOf(JAR_FILE_ENTRY_SEPARATOR);
        if (separatorIndex != -1) {
            resourcePath = new Path(resourcePathString.substring(0, separatorIndex))
                    .append(new Path(resourcePathString.substring(separatorIndex + 1)));
        } else {
            resourcePath = new Path(resourcePathString);
        }
        return this.encloses(resourcePath);
    }

    /**
     * Returns whether this search scope encloses the given path.
     */
    private boolean encloses(IPath path) {
        for (int i = 0; i < this.pathsCount; i++) {
            if (this.pathWithSubFolders[i]) {
                if (this.paths[i].isPrefixOf(path)) {
                    return true;
                }
            } else {
                IPath scopePath = this.paths[i];
                if (scopePath.isPrefixOf(path) && (scopePath.segmentCount() == path.segmentCount() - 1)) {
                    return true;
                }
            }
        }
        return false;
    }

    /*
     * (non-Javadoc)
     * 
     * @see IJavaSearchScope#encloses(IJavaElement)
     */
    public boolean encloses(IJavaElement element) {
        if (this.elements != null) {
            for (int i = 0, length = this.elements.size(); i < length; i++) {
                IJavaElement scopeElement = (IJavaElement) this.elements.get(i);
                IJavaElement searchedElement = element;
                while (searchedElement != null) {
                    if (searchedElement.equals(scopeElement)) {
                        return true;
                    }
                    searchedElement = searchedElement.getParent();
                }
            }
            return false;
        }
        return this.encloses(this.fullPath(element));
    }

    /*
     * (non-Javadoc)
     * 
     * @see IJavaSearchScope#enclosingProjectsAndJars()
     */
    public IPath[] enclosingProjectsAndJars() {
        return this.enclosingProjectsAndJars;
    }

    private IPath fullPath(IJavaElement element) {
        if (element instanceof IPackageFragmentRoot) {
            return ((IPackageFragmentRoot) element).getPath();
        }
        IJavaElement parent = element.getParent();
        IPath parentPath = parent == null ? null : this.fullPath(parent);
        IPath childPath;
        if (element instanceof IPackageFragment) {
            childPath = new Path(element.getElementName().replace('.', '/'));
        } else if (element instanceof IOpenable) {
            childPath = new Path(element.getElementName());
        } else {
            return parentPath;
        }
        return parentPath == null ? childPath : parentPath.append(childPath);
    }

    protected void initialize() {
        this.paths = new IPath[1];
        this.pathWithSubFolders = new boolean[1];
        this.pathsCount = 0;
        this.enclosingProjectsAndJars = new IPath[0];
    }

    /**
     * Gets the includeExportedClassPathEntriesOnly.
     * 
     * @return Returns a boolean
     */
    public boolean includeExportedClassPathEntriesOnly() {
        return includeExportedClassPathEntriesOnly;
    }

    /**
     * Sets the includeExportedClassPathEntriesOnly.
     * 
     * @param includeExportedClassPathEntriesOnly
     *            The includeExportedClassPathEntriesOnly to set
     */
    public void setIncludeExportedClassPathEntriesOnly(boolean includeExportedClassPathEntriesOnly) {
        this.includeExportedClassPathEntriesOnly = includeExportedClassPathEntriesOnly;
    }

    /**
     * @see IJavaSearchScope#includesBinaries()
     * @deprecated
     */
    public boolean includesBinaries() {
        return true;
    }

    /**
     * @see IJavaSearchScope#includesClasspaths()
     * @deprecated
     */
    public boolean includesClasspaths() {
        return true;
    }

    /**
     * @see IJavaSearchScope#setIncludesBinaries(boolean)
     * @deprecated
     */
    public void setIncludesBinaries(boolean includesBinaries) {
        //Default nothing
    }

    /**
     * @see IJavaSearchScope#setIncludesClasspaths(boolean)
     * @deprecated
     */
    public void setIncludesClasspaths(boolean includesClasspaths) {
        //Default nothing
    }

}