package org.eclipse.jdt.internal.core;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IModularClassFile;
import org.eclipse.jdt.core.IOrdinaryClassFile;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IParent;
import org.eclipse.jdt.core.ISourceManipulation;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.WorkingCopyOwner;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
import org.eclipse.jdt.internal.core.JavaModelManager.PerProjectInfo;
import org.eclipse.jdt.internal.core.util.MementoTokenizer;
import org.eclipse.jdt.internal.core.util.Messages;
import org.eclipse.jdt.internal.core.util.Util;
@SuppressWarnings({"rawtypes", "unchecked"})
public class PackageFragment extends Openable implements IPackageFragment, SuffixConstants {
protected static final IClassFile[] NO_CLASSFILES = new IClassFile[] {};
protected static final IOrdinaryClassFile[] NO_ORDINARY_CLASSFILES = new IOrdinaryClassFile[] {};
protected static final ICompilationUnit[] NO_COMPILATION_UNITS = new ICompilationUnit[] {};
public String[] names;
private boolean isValidPackageName;
protected PackageFragment(PackageFragmentRoot root, String[] names) {
super(root);
this.names = names;
this.isValidPackageName = internalIsValidPackageName();
}
@Override
protected boolean buildStructure(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException {
HashSet vChildren = new HashSet();
int kind = getKind();
try {
PackageFragmentRoot root = getPackageFragmentRoot();
char[][] inclusionPatterns = root.fullInclusionPatternChars();
char[][] exclusionPatterns = root.fullExclusionPatternChars();
IResource[] members = ((IContainer) underlyingResource).members();
int length = members.length;
if (length > 0) {
IJavaProject project = getJavaProject();
String sourceLevel = project.getOption(JavaCore.COMPILER_SOURCE, true);
String complianceLevel = project.getOption(JavaCore.COMPILER_COMPLIANCE, true);
for (int i = 0; i < length; i++) {
IResource child = members[i];
if (child.getType() != IResource.FOLDER
&& !Util.isExcluded(child, inclusionPatterns, exclusionPatterns)) {
IJavaElement childElement;
if (kind == IPackageFragmentRoot.K_SOURCE && Util.isValidCompilationUnitName(child.getName(), sourceLevel, complianceLevel)) {
childElement = new CompilationUnit(this, child.getName(), DefaultWorkingCopyOwner.PRIMARY);
vChildren.add(childElement);
} else if (kind == IPackageFragmentRoot.K_BINARY && Util.isValidClassFileName(child.getName(), sourceLevel, complianceLevel)) {
childElement = getClassFile(child.getName());
vChildren.add(childElement);
}
}
}
}
} catch (CoreException e) {
throw new JavaModelException(e);
}
if (kind == IPackageFragmentRoot.K_SOURCE) {
ICompilationUnit[] primaryCompilationUnits = getCompilationUnits(DefaultWorkingCopyOwner.PRIMARY);
for (int i = 0, length = primaryCompilationUnits.length; i < length; i++) {
ICompilationUnit primary = primaryCompilationUnits[i];
vChildren.add(primary);
}
}
if (!vChildren.isEmpty()) {
IJavaElement[] children = new IJavaElement[vChildren.size()];
vChildren.toArray(children);
info.setChildren(children);
} else {
info.setChildren(JavaElement.NO_ELEMENTS);
}
return true;
}
@Override
public boolean containsJavaResources() throws JavaModelException {
return ((PackageFragmentInfo) getElementInfo()).containsJavaResources();
}
@Override
public void copy(IJavaElement container, IJavaElement sibling, String rename, boolean force, IProgressMonitor monitor) throws JavaModelException {
if (container == null) {
throw new IllegalArgumentException(Messages.operation_nullContainer);
}
IJavaElement[] elements= new IJavaElement[] {this};
IJavaElement[] containers= new IJavaElement[] {container};
IJavaElement[] siblings= null;
if (sibling != null) {
siblings= new IJavaElement[] {sibling};
}
String[] renamings= null;
if (rename != null) {
renamings= new String[] {rename};
}
getJavaModel().copy(elements, containers, siblings, renamings, force, monitor);
}
@Override
public ICompilationUnit createCompilationUnit(String cuName, String contents, boolean force, IProgressMonitor monitor) throws JavaModelException {
CreateCompilationUnitOperation op= new CreateCompilationUnitOperation(this, cuName, contents, force);
op.runOperation(monitor);
return new CompilationUnit(this, cuName, DefaultWorkingCopyOwner.PRIMARY);
}
@Override
protected Object createElementInfo() {
return new PackageFragmentInfo();
}
@Override
public void delete(boolean force, IProgressMonitor monitor) throws JavaModelException {
IJavaElement[] elements = new IJavaElement[] {this};
getJavaModel().delete(elements, force, monitor);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof PackageFragment)) return false;
PackageFragment other = (PackageFragment) o;
return Util.equalArraysOrNull(this.names, other.names) &&
this.parent.equals(other.parent);
}
@Override
public boolean exists() {
return super.exists() && !Util.isExcluded(this) && isValidPackageName();
}
@Override
public IOrdinaryClassFile getOrdinaryClassFile(String classFileName) {
if (!org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(classFileName)) {
throw new IllegalArgumentException(Messages.bind(Messages.element_invalidClassFileName, classFileName));
}
if (TypeConstants.MODULE_INFO_CLASS_NAME_STRING.equals(classFileName)) {
throw new IllegalArgumentException(Messages.element_moduleInfoNotSupported);
}
int length = classFileName.length() - 6;
char[] nameWithoutExtension = new char[length];
classFileName.getChars(0, length, nameWithoutExtension, 0);
return new ClassFile(this, new String(nameWithoutExtension));
}
@Override
public IClassFile getClassFile(String classFileName) {
if (TypeConstants.MODULE_INFO_CLASS_NAME_STRING.equals(classFileName))
return getModularClassFile();
return getOrdinaryClassFile(classFileName);
}
@Override
public IModularClassFile getModularClassFile() {
return new ModularClassFile(this);
}
@Override
public IOrdinaryClassFile[] getOrdinaryClassFiles() throws JavaModelException {
if (getKind() == IPackageFragmentRoot.K_SOURCE) {
return NO_ORDINARY_CLASSFILES;
}
ArrayList list = getChildrenOfType(CLASS_FILE);
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
if (iterator.next() instanceof ModularClassFile)
iterator.remove();
}
IOrdinaryClassFile[] array= new IOrdinaryClassFile[list.size()];
list.toArray(array);
return array;
}
@Override
public IClassFile[] getAllClassFiles() throws JavaModelException {
if (getKind() == IPackageFragmentRoot.K_SOURCE) {
return NO_CLASSFILES;
}
ArrayList list = getChildrenOfType(CLASS_FILE);
IClassFile[] array= new IClassFile[list.size()];
list.toArray(array);
return array;
}
@Deprecated
@Override
public IClassFile[] getClassFiles() throws JavaModelException {
return getOrdinaryClassFiles();
}
@Override
public ICompilationUnit getCompilationUnit(String cuName) {
if (!org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(cuName)) {
throw new IllegalArgumentException(Messages.convention_unit_notJavaName);
}
return new CompilationUnit(this, cuName, DefaultWorkingCopyOwner.PRIMARY);
}
@Override
public ICompilationUnit[] getCompilationUnits() throws JavaModelException {
if (getKind() == IPackageFragmentRoot.K_BINARY) {
return NO_COMPILATION_UNITS;
}
ArrayList list = getChildrenOfType(COMPILATION_UNIT);
ICompilationUnit[] array= new ICompilationUnit[list.size()];
list.toArray(array);
return array;
}
@Override
public ICompilationUnit[] getCompilationUnits(WorkingCopyOwner owner) {
ICompilationUnit[] workingCopies = JavaModelManager.getJavaModelManager().getWorkingCopies(owner, false);
if (workingCopies == null) return JavaModelManager.NO_WORKING_COPY;
int length = workingCopies.length;
ICompilationUnit[] result = new ICompilationUnit[length];
int index = 0;
for (int i = 0; i < length; i++) {
ICompilationUnit wc = workingCopies[i];
if (equals(wc.getParent()) && !Util.isExcluded(wc)) {
result[index++] = wc;
}
}
if (index != length) {
System.arraycopy(result, 0, result = new ICompilationUnit[index], 0, index);
}
return result;
}
@Override
public String getElementName() {
if (this.names.length == 0)
return DEFAULT_PACKAGE_NAME;
return Util.concatWith(this.names, '.');
}
@Override
public int getElementType() {
return PACKAGE_FRAGMENT;
}
@Override
public IJavaElement getHandleFromMemento(String token, MementoTokenizer memento, WorkingCopyOwner owner) {
switch (token.charAt(0)) {
case JEM_CLASSFILE:
if (!memento.hasMoreTokens()) return this;
String classFileName = memento.nextToken();
JavaElement classFile = (JavaElement) getClassFile(classFileName);
return classFile.getHandleFromMemento(memento, owner);
case JEM_MODULAR_CLASSFILE:
classFile = (JavaElement) getModularClassFile();
return classFile.getHandleFromMemento(memento, owner);
case JEM_COMPILATIONUNIT:
if (!memento.hasMoreTokens()) return this;
String cuName = memento.nextToken();
JavaElement cu = new CompilationUnit(this, cuName, owner);
return cu.getHandleFromMemento(memento, owner);
}
return null;
}
@Override
protected char getHandleMementoDelimiter() {
return JavaElement.JEM_PACKAGEFRAGMENT;
}
@Override
public int getKind() throws JavaModelException {
return ((IPackageFragmentRoot)getParent()).getKind();
}
@Override
public Object[] getNonJavaResources() throws JavaModelException {
if (isDefaultPackage()) {
return JavaElementInfo.NO_NON_JAVA_RESOURCES;
} else {
return ((PackageFragmentInfo) getElementInfo()).getNonJavaResources(resource(), getPackageFragmentRoot());
}
}
@Override
public IPath getPath() {
PackageFragmentRoot root = getPackageFragmentRoot();
if (root.isArchive()) {
return root.getPath();
} else {
IPath path = root.getPath();
for (int i = 0, length = this.names.length; i < length; i++) {
String name = this.names[i];
path = path.append(name);
}
return path;
}
}
@Override
public IResource resource(PackageFragmentRoot root) {
int length = this.names.length;
if (length == 0) {
return root.resource(root);
} else {
IPath path = new Path(this.names[0]);
for (int i = 1; i < length; i++)
path = path.append(this.names[i]);
return ((IContainer)root.resource(root)).getFolder(path);
}
}
@Override
public IResource getUnderlyingResource() throws JavaModelException {
IResource rootResource = this.parent.getUnderlyingResource();
if (rootResource == null) {
return null;
}
if (rootResource.getType() == IResource.FOLDER || rootResource.getType() == IResource.PROJECT) {
IContainer folder = (IContainer) rootResource;
String[] segs = this.names;
for (int i = 0; i < segs.length; ++i) {
IResource child = folder.findMember(segs[i]);
if (child == null || child.getType() != IResource.FOLDER) {
throw newNotPresentException();
}
folder = (IFolder) child;
}
return folder;
} else {
return rootResource;
}
}
@Override
public int hashCode() {
int hash = this.parent.hashCode();
for (int i = 0, length = this.names.length; i < length; i++)
hash = Util.combineHashCodes(this.names[i].hashCode(), hash);
return hash;
}
@Override
public boolean hasChildren() throws JavaModelException {
return getChildren().length > 0;
}
@Override
public boolean hasSubpackages() throws JavaModelException {
IJavaElement[] packages= ((IPackageFragmentRoot)getParent()).getChildren();
int namesLength = this.names.length;
nextPackage: for (int i= 0, length = packages.length; i < length; i++) {
String[] otherNames = ((PackageFragment) packages[i]).names;
if (otherNames.length <= namesLength) continue nextPackage;
for (int j = 0; j < namesLength; j++)
if (!this.names[j].equals(otherNames[j]))
continue nextPackage;
return true;
}
return false;
}
protected boolean internalIsValidPackageName() {
IJavaProject javaProject = JavaCore.create(resource().getProject());
String sourceLevel = javaProject.getOption(JavaCore.COMPILER_SOURCE, true);
String complianceLevel = javaProject.getOption(JavaCore.COMPILER_COMPLIANCE, true);
for (int i = 0, length = this.names.length; i < length; i++) {
if (!Util.isValidFolderNameForPackage(this.names[i], sourceLevel, complianceLevel))
return false;
}
return true;
}
@Override
public boolean isDefaultPackage() {
return this.names.length == 0;
}
protected final boolean isValidPackageName() {
return this.isValidPackageName;
}
@Override
public void move(IJavaElement container, IJavaElement sibling, String rename, boolean force, IProgressMonitor monitor) throws JavaModelException {
if (container == null) {
throw new IllegalArgumentException(Messages.operation_nullContainer);
}
IJavaElement[] elements= new IJavaElement[] {this};
IJavaElement[] containers= new IJavaElement[] {container};
IJavaElement[] siblings= null;
if (sibling != null) {
siblings= new IJavaElement[] {sibling};
}
String[] renamings= null;
if (rename != null) {
renamings= new String[] {rename};
}
getJavaModel().move(elements, containers, siblings, renamings, force, monitor);
}
@Override
public void rename(String newName, boolean force, IProgressMonitor monitor) throws JavaModelException {
if (newName == null) {
throw new IllegalArgumentException(Messages.element_nullName);
}
IJavaElement[] elements= new IJavaElement[] {this};
IJavaElement[] dests= new IJavaElement[] {getParent()};
String[] renamings= new String[] {newName};
getJavaModel().rename(elements, dests, renamings, force, monitor);
}
@Override
protected void toStringChildren(int tab, StringBuffer buffer, Object info) {
if (tab == 0) {
super.toStringChildren(tab, buffer, info);
}
}
@Override
protected void toStringInfo(int tab, StringBuffer buffer, Object info, boolean showResolvedInfo) {
buffer.append(tabString(tab));
if (this.names.length == 0) {
buffer.append("<default>");
} else {
toStringName(buffer);
}
if (info == null) {
buffer.append(" (not open)");
} else {
if (tab > 0) {
buffer.append(" (...)");
}
}
}
@Override
public String getAttachedJavadoc(IProgressMonitor monitor) throws JavaModelException {
PerProjectInfo projectInfo = JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(getJavaProject().getProject());
String cachedJavadoc = null;
synchronized (projectInfo.javadocCache) {
cachedJavadoc = (String) projectInfo.javadocCache.get(this);
}
if (cachedJavadoc != null) {
return cachedJavadoc;
}
URL baseLocation= getJavadocBaseLocation();
if (baseLocation == null) {
return null;
}
StringBuffer pathBuffer = new StringBuffer(baseLocation.toExternalForm());
if (!(pathBuffer.charAt(pathBuffer.length() - 1) == '/')) {
pathBuffer.append('/');
}
String packPath= getElementName().replace('.', '/');
pathBuffer.append(packPath).append('/').append(JavadocConstants.PACKAGE_FILE_NAME);
if (monitor != null && monitor.isCanceled()) throw new OperationCanceledException();
String contents = getURLContents(baseLocation, String.valueOf(pathBuffer));
if (monitor != null && monitor.isCanceled()) throw new OperationCanceledException();
if (contents == null) return null;
contents = (new JavadocContents(contents)).getPackageDoc();
if (contents == null) contents = "";
synchronized (projectInfo.javadocCache) {
projectInfo.javadocCache.put(this, contents);
}
return contents;
}
@Override
protected IStatus validateExistence(IResource underlyingResource) {
if (!isValidPackageName())
return newDoesNotExistStatus();
if (underlyingResource != null && !resourceExists(underlyingResource))
return newDoesNotExistStatus();
int kind;
try {
kind = getKind();
} catch (JavaModelException e) {
return e.getStatus();
}
if (kind == IPackageFragmentRoot.K_SOURCE && Util.isExcluded(this))
return newDoesNotExistStatus();
return JavaModelStatus.VERIFIED_OK;
}
}