blob: 8e7f5c1e9f4cf8c937f1bd426b247ce79bdcaa7b [file] [log] [blame]
package org.eclipse.jdt.internal.core;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import java.util.*;
import org.eclipse.jdt.core.*;
import org.eclipse.core.runtime.CoreException;
/**
* @see IPackageFragmentRoot
*/
public class PackageFragmentRoot extends Openable implements IPackageFragmentRoot {
/**
* The resource associated with this root.
* @see IResource
*/
protected IResource fResource;
/**
* Constructs a package fragment root which is the root of the java package
* directory hierarchy.
*/
protected PackageFragmentRoot(IResource resource, IJavaProject project) {
this(resource, project, resource.getProjectRelativePath().toString());
fResource = resource;
}
/**
* Constructs a package fragment root which is the root of the java package
* directory hierarchy.
*/
protected PackageFragmentRoot(IResource resource, IJavaProject project, String path) {
super(PACKAGE_FRAGMENT_ROOT, project, path);
fResource = resource;
}
/**
* @see IPackageFragmentRoot
*/
public void attachSource(IPath zipPath, IPath rootPath, IProgressMonitor monitor) throws JavaModelException {
throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, this));
}
/**
* Compute the package fragment children of this package fragment root.
*
* @exception JavaModelException The resource associated with this package fragment root does not exist
*/
protected boolean computeChildren(OpenableElementInfo info) throws JavaModelException {
try {
// the underlying resource may be a folder or a project (in the case that the project folder
// is actually the package fragment root)
if (fResource.getType() == IResource.FOLDER || fResource.getType() == IResource.PROJECT) {
ArrayList vChildren = new ArrayList(5);
computeFolderChildren((IContainer) fResource, "", vChildren); //$NON-NLS-1$
IJavaElement[] children = new IJavaElement[vChildren.size()];
vChildren.toArray(children);
info.setChildren(children);
}
} catch (JavaModelException e) {
//problem resolving children; structure remains unknown
info.setChildren(new IJavaElement[]{});
throw e;
}
return true;
}
/**
* Starting at this folder, create package fragments and add the fragments to the collection
* of children.
*
* @exception JavaModelException The resource associated with this package fragment does not exist
*/
protected void computeFolderChildren(IContainer folder, String prefix, ArrayList vChildren) throws JavaModelException {
IPackageFragment pkg = getPackageFragment(prefix);
vChildren.add(pkg);
try {
IPath outputLocationPath = getJavaProject().getOutputLocation();
IResource[] members = folder.members();
for (int i = 0, max = members.length; i < max; i++) {
IResource member = members[i];
String memberName = member.getName();
if (member.getType() == IResource.FOLDER
&& Util.isValidFolderNameForPackage(memberName)) {
String newPrefix;
if (prefix.length() == 0) {
newPrefix = memberName;
} else {
newPrefix = prefix + "." + memberName; //$NON-NLS-1$
}
// eliminate binary output only if nested inside direct subfolders
if (!member.getFullPath().equals(outputLocationPath)) {
computeFolderChildren((IFolder) member, newPrefix, vChildren);
}
}
}
} catch(IllegalArgumentException e){
throw new JavaModelException(e, IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST); // could be thrown by ElementTree when path is not found
} catch (CoreException e) {
throw new JavaModelException(e);
}
}
/**
* Returns a new element info for this element.
*/
protected OpenableElementInfo createElementInfo() {
return new PackageFragmentRootInfo();
}
/**
* @see IPackageFragmentRoot
*/
public IPackageFragment createPackageFragment(String name, boolean force, IProgressMonitor monitor) throws JavaModelException {
CreatePackageFragmentOperation op = new CreatePackageFragmentOperation(this, name, force);
runOperation(op, monitor);
return getPackageFragment(name);
}
/**
* Returns the root's kind - K_SOURCE or K_BINARY, defaults
* to K_SOURCE if it is not on the classpath.
*
* @exception NotPresentException if the project and root do
* not exist.
*/
protected int determineKind(IResource underlyingResource) throws JavaModelException {
IClasspathEntry[] entries= ((JavaProject)getJavaProject()).getExpandedClasspath(true);
for (int i= 0; i < entries.length; i++) {
IClasspathEntry entry= entries[i];
if (entry.getPath().equals(underlyingResource.getFullPath())) {
return entry.getContentKind();
}
}
return IPackageFragmentRoot.K_SOURCE;
}
/**
* Compares two objects for equality;
* for <code>PackageFragmentRoot</code>s, equality is having the
* same <code>JavaModel</code>, same resources, and occurrence count.
*
*/
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof PackageFragmentRoot))
return false;
PackageFragmentRoot other = (PackageFragmentRoot) o;
return getJavaModel().equals(other.getJavaModel()) &&
fResource.equals(other.fResource) &&
fOccurrenceCount == other.fOccurrenceCount;
}
/**
* @see IJavaElement
*/
public boolean exists() {
return super.exists()
&& isOnClasspath();
}
/**
* @see Openable
*/
protected boolean generateInfos(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException {
((PackageFragmentRootInfo) info).setRootKind(determineKind(underlyingResource));
return computeChildren(info);
}
/**
* @see JavaElement#getHandleMemento()
*/
protected char getHandleMementoDelimiter() {
return JavaElement.JEM_PACKAGEFRAGMENTROOT;
}
/**
* @see IPackageFragmentRoot
*/
public int getKind() throws JavaModelException {
return ((PackageFragmentRootInfo)getElementInfo()).getRootKind();
}
/**
* Returns an array of non-java resources contained in the receiver.
*/
public Object[] getNonJavaResources() throws JavaModelException {
return ((PackageFragmentRootInfo) getElementInfo()).getNonJavaResources(getJavaProject(), getUnderlyingResource());
}
/**
* @see IPackageFragmentRoot
*/
public IPackageFragment getPackageFragment(String packageName) {
return new PackageFragment(this, packageName);
}
/**
* Returns the package name for the given folder
* (which is a decendent of this root).
*/
protected String getPackageName(IFolder folder) throws JavaModelException {
IPath myPath= getPath();
IPath pkgPath= folder.getFullPath();
int mySegmentCount= myPath.segmentCount();
int pkgSegmentCount= pkgPath.segmentCount();
StringBuffer name = new StringBuffer(IPackageFragment.DEFAULT_PACKAGE_NAME);
for (int i= mySegmentCount; i < pkgSegmentCount; i++) {
if (i > mySegmentCount) {
name.append('.');
}
name.append(pkgPath.segment(i));
}
return name.toString();
}
/**
* @see IJavaElement
*/
public IPath getPath() {
return fResource.getFullPath();
}
/*
* @see IPackageFragmentRoot
*/
public IClasspathEntry getRawClasspathEntry() throws JavaModelException {
IPath path= this.getPath();
IClasspathEntry[] entries= this.getJavaProject().getRawClasspath();
for (int i= 0; i < entries.length; i++) {
IClasspathEntry entry = entries[i];
switch (entry.getEntryKind()) {
case IClasspathEntry.CPE_PROJECT:
// a root's project always refers directly to the root
// no need to follow the project reference
continue;
case IClasspathEntry.CPE_CONTAINER:
IClasspathContainer container = JavaCore.getClasspathContainer(entry.getPath(), this.getJavaProject());
if (container != null){
IClasspathEntry[] containerEntries = container.getClasspathEntries();
for (int j = 0; j < containerEntries.length; j++){
IClasspathEntry containerEntry = JavaCore.getResolvedClasspathEntry(containerEntries[j]);
if (containerEntry != null && path.equals(containerEntry.getPath())) {
return entry; // answer original entry
}
}
}
break;
case IClasspathEntry.CPE_VARIABLE:
entry = JavaCore.getResolvedClasspathEntry(entry);
// don't break so as to run default
default:
if (entry != null && path.equals(entry.getPath())) {
return entries[i];
}
}
}
return null;
}
/*
* @see IJavaElement
*/
public IResource getResource() {
return fResource;
}
/**
* Cannot attach source to a folder.
*
* @see IPackageFragmentRoot
*/
public IPath getSourceAttachmentPath() throws JavaModelException {
return null;
}
/**
* Cannot attach source to a folder.
*
* @see IPackageFragmentRoot
*/
public IPath getSourceAttachmentRootPath() throws JavaModelException {
return null;
}
/**
* @see IJavaElement
*/
public IResource getUnderlyingResource() throws JavaModelException {
if (fResource.exists()) {
return fResource;
} else {
throw newNotPresentException();
}
}
public int hashCode() {
return fResource.hashCode();
}
/**
* @see IPackageFragmentRoot
*/
public boolean isArchive() {
return false;
}
/**
* @see IPackageFragmentRoot
*/
public boolean isExternal() {
return false;
}
/*
* Returns whether this package fragment root is on the classpath of its project.
*/
protected boolean isOnClasspath() {
IJavaProject project = this.getJavaProject();
if (this.getElementType() == IJavaElement.JAVA_PROJECT){
return true;
}
IPath path = this.getPath();
try {
// check package fragment root on classpath of its project
IClasspathEntry[] classpath = project.getResolvedClasspath(true);
for (int i = 0, length = classpath.length; i < length; i++) {
IClasspathEntry entry = classpath[i];
if (entry.getPath().equals(path)) {
return true;
}
}
} catch(JavaModelException e){
// could not read classpath, then assume it is outside
}
return false;
}
protected void openWhenClosed(IProgressMonitor pm) throws JavaModelException {
if (!this.resourceExists() || !this.isOnClasspath()) throw newNotPresentException();
super.openWhenClosed(pm);
}
/**
* Recomputes the children of this element, based on the current state
* of the workbench.
*/
public void refreshChildren() {
try {
OpenableElementInfo info= (OpenableElementInfo)getElementInfo();
computeChildren(info);
} catch (JavaModelException e) {
// do nothing.
}
}
/*
* @see JavaElement#rootedAt(IJavaProject)
*/
public IJavaElement rootedAt(IJavaProject project) {
return
new PackageFragmentRoot(
fResource,
project,
fName);
}
/**
* @private Debugging purposes
*/
protected void toStringInfo(int tab, StringBuffer buffer, Object info) {
buffer.append(this.tabString(tab));
if (getElementName().length() == 0) {
buffer.append("[project root]"); //$NON-NLS-1$
} else {
buffer.append(getElementName());
}
if (info == null) {
buffer.append(" (not open)"); //$NON-NLS-1$
}
}
}