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.*; | |
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; | |
import org.eclipse.jdt.core.*; | |
import org.eclipse.jdt.internal.core.util.*; | |
import java.io.File; | |
import java.util.*; | |
/** | |
* Implementation of <code>IJavaModel<code>. The Java Model maintains a cache of | |
* active <code>IJavaProject</code>s in a workspace. A Java Model is specific to a | |
* workspace. To retrieve a workspace's model, use the | |
* <code>#getJavaModel(IWorkspace)</code> method. | |
* | |
* @see IJavaModel | |
*/ | |
public class JavaModel extends Openable implements IJavaModel { | |
/** | |
* A set of java.io.Files used as a cache of external jars that | |
* are known to be existing. | |
* Note this cache is kept for the whole session. | |
*/ | |
public static HashSet existingExternalFiles = new HashSet(); | |
/** | |
* Constructs a new Java Model on the given workspace. | |
* | |
* @exception Error if called more than once | |
*/ | |
protected JavaModel() throws Error { | |
super(JAVA_MODEL, null, "" /*workspace has empty name*/); //$NON-NLS-1$ | |
} | |
/** | |
* @see IJavaModel | |
*/ | |
public void copy(IJavaElement[] elements, IJavaElement[] containers, IJavaElement[] siblings, String[] renamings, boolean force, IProgressMonitor monitor) throws JavaModelException { | |
if (elements != null && elements[0] != null && elements[0].getElementType() < IJavaElement.TYPE) { | |
runOperation(new CopyResourceElementsOperation(elements, containers, force), elements, siblings, renamings, monitor); | |
} else { | |
runOperation(new CopyElementsOperation(elements, containers, force), elements, siblings, renamings, monitor); | |
} | |
} | |
/** | |
* Returns a new element info for this element. | |
*/ | |
protected OpenableElementInfo createElementInfo() { | |
return new JavaModelInfo(this); | |
} | |
/** | |
* @see IJavaModel | |
*/ | |
public void delete(IJavaElement[] elements, boolean force, IProgressMonitor monitor) throws JavaModelException { | |
if (elements != null && elements[0] != null && elements[0].getElementType() < IJavaElement.TYPE) { | |
runOperation(new DeleteResourceElementsOperation(elements, force), monitor); | |
} else { | |
runOperation(new DeleteElementsOperation(elements, force), monitor); | |
} | |
} | |
/** | |
* Finds the given project in the list of the java model's children. | |
* Returns null if not found. | |
*/ | |
public IJavaProject findJavaProject(IProject project) { | |
try { | |
IJavaProject[] projects = this.getJavaProjects(); | |
for (int i = 0, length = projects.length; i < length; i++) { | |
IJavaProject javaProject = projects[i]; | |
if (project.equals(javaProject.getProject())) { | |
return javaProject; | |
} | |
} | |
} catch (JavaModelException e) { | |
} | |
return null; | |
} | |
/** | |
*/ | |
protected boolean generateInfos( | |
OpenableElementInfo info, | |
IProgressMonitor pm, | |
Map newElements, | |
IResource underlyingResource) throws JavaModelException { | |
fgJavaModelManager.putInfo(((JavaModelInfo) info).getJavaModel(), info); | |
// determine my children | |
try { | |
IProject[] projects = this.getWorkspace().getRoot().getProjects(); | |
for (int i = 0, max = projects.length; i < max; i++) { | |
IProject project = projects[i]; | |
if (project.isOpen() && project.hasNature(JavaCore.NATURE_ID)) { | |
info.addChild(getJavaProject(project)); | |
} | |
} | |
} catch (CoreException e) { | |
throw new JavaModelException(e); | |
} | |
return true; | |
} | |
/** | |
* Returns the <code>IJavaElement</code> represented by the <code>String</code> | |
* memento. | |
* @see getHandleMemento() | |
*/ | |
protected IJavaElement getHandleFromMementoForBinaryMembers(String memento, IPackageFragmentRoot root, int rootEnd, int end) throws JavaModelException { | |
//deal with class file and binary members | |
IPackageFragment frag = null; | |
if (rootEnd == end - 1) { | |
//default package | |
frag= root.getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME); | |
} else { | |
frag= root.getPackageFragment(memento.substring(rootEnd + 1, end)); | |
} | |
int oldEnd = end; | |
end = memento.indexOf(JavaElement.JEM_TYPE, oldEnd); | |
if (end == -1) { | |
//we ended with a class file | |
return frag.getClassFile(memento.substring(oldEnd + 1)); | |
} | |
IClassFile cf = frag.getClassFile(memento.substring(oldEnd + 1, end)); | |
oldEnd = end; | |
end = memento.indexOf(JavaElement.JEM_TYPE, oldEnd); | |
oldEnd = end; | |
end = memento.indexOf(JavaElement.JEM_FIELD, end); | |
if (end != -1) { | |
//binary field | |
IType type = cf.getType(); | |
return type.getField(memento.substring(end + 1)); | |
} | |
end = memento.indexOf(JavaElement.JEM_METHOD, oldEnd); | |
if (end != -1) { | |
//binary method | |
oldEnd = end; | |
IType type = cf.getType(); | |
String methodName; | |
end = memento.lastIndexOf(JavaElement.JEM_METHOD); | |
String[] parameterTypes = null; | |
if (end == oldEnd) { | |
methodName = memento.substring(end + 1); | |
//no parameter types | |
parameterTypes = new String[] {}; | |
} else { | |
String parameters = memento.substring(oldEnd + 1); | |
StringTokenizer tokenizer = new StringTokenizer(parameters, new String(new char[] {JavaElement.JEM_METHOD})); | |
parameterTypes = new String[tokenizer.countTokens() - 1]; | |
methodName= tokenizer.nextToken(); | |
int i = 0; | |
while (tokenizer.hasMoreTokens()) { | |
parameterTypes[i] = tokenizer.nextToken(); | |
i++; | |
} | |
} | |
return type.getMethod(methodName, parameterTypes); | |
} | |
//binary type | |
return cf.getType(); | |
} | |
/** | |
* Returns the <code>IJavaElement</code> represented by the <code>String</code> | |
* memento. | |
* @see getHandleMemento() | |
*/ | |
protected IJavaElement getHandleFromMementoForSourceMembers(String memento, IPackageFragmentRoot root, int rootEnd, int end) throws JavaModelException { | |
//deal with compilation units and source members | |
IPackageFragment frag = null; | |
if (rootEnd == end - 1) { | |
//default package | |
frag= root.getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME); | |
} else { | |
frag= root.getPackageFragment(memento.substring(rootEnd + 1, end)); | |
} | |
int oldEnd = end; | |
end = memento.indexOf(JavaElement.JEM_PACKAGEDECLARATION, end); | |
if (end != -1) { | |
//package declaration | |
ICompilationUnit cu = frag.getCompilationUnit(memento.substring(oldEnd + 1, end)); | |
return cu.getPackageDeclaration(memento.substring(end + 1)); | |
} | |
end = memento.indexOf(JavaElement.JEM_IMPORTDECLARATION, oldEnd); | |
if (end != -1) { | |
//import declaration | |
ICompilationUnit cu = frag.getCompilationUnit(memento.substring(oldEnd + 1, end)); | |
return cu.getImport(memento.substring(end + 1)); | |
} | |
int typeStart = memento.indexOf(JavaElement.JEM_TYPE, oldEnd); | |
if (typeStart == -1) { | |
//we ended with a compilation unit | |
return frag.getCompilationUnit(memento.substring(oldEnd + 1)); | |
} | |
//source members | |
ICompilationUnit cu = frag.getCompilationUnit(memento.substring(oldEnd + 1, typeStart)); | |
end = memento.indexOf(JavaElement.JEM_FIELD, oldEnd); | |
if (end != -1) { | |
//source field | |
IType type = getHandleFromMementoForSourceType(memento, cu, typeStart, end); | |
return type.getField(memento.substring(end + 1)); | |
} | |
end = memento.indexOf(JavaElement.JEM_METHOD, oldEnd); | |
if (end != -1) { | |
//source method | |
IType type = getHandleFromMementoForSourceType(memento, cu, typeStart, end); | |
oldEnd = end; | |
String methodName; | |
end = memento.lastIndexOf(JavaElement.JEM_METHOD); | |
String[] parameterTypes = null; | |
if (end == oldEnd) { | |
methodName = memento.substring(end + 1); | |
//no parameter types | |
parameterTypes = new String[] {}; | |
} else { | |
String parameters = memento.substring(oldEnd + 1); | |
StringTokenizer mTokenizer = new StringTokenizer(parameters, new String(new char[] {JavaElement.JEM_METHOD})); | |
parameterTypes = new String[mTokenizer.countTokens() - 1]; | |
methodName = mTokenizer.nextToken(); | |
int i = 0; | |
while (mTokenizer.hasMoreTokens()) { | |
parameterTypes[i] = mTokenizer.nextToken(); | |
i++; | |
} | |
} | |
return type.getMethod(methodName, parameterTypes); | |
} | |
end = memento.indexOf(JavaElement.JEM_INITIALIZER, oldEnd); | |
if (end != -1 ) { | |
//initializer | |
IType type = getHandleFromMementoForSourceType(memento, cu, typeStart, end); | |
return type.getInitializer(Integer.parseInt(memento.substring(end + 1))); | |
} | |
//source type | |
return getHandleFromMementoForSourceType(memento, cu, typeStart, memento.length()); | |
} | |
/** | |
* Returns the <code>IJavaElement</code> represented by the <code>String</code> | |
* memento. | |
* @see getHandleMemento() | |
*/ | |
protected IType getHandleFromMementoForSourceType(String memento, ICompilationUnit cu, int typeStart, int typeEnd) throws JavaModelException { | |
int end = memento.lastIndexOf(JavaElement.JEM_TYPE); | |
IType type = null; | |
if (end == typeStart) { | |
String typeName = memento.substring(typeStart + 1, typeEnd); | |
type = cu.getType(typeName); | |
} else { | |
String typeNames = memento.substring(typeStart + 1, typeEnd); | |
StringTokenizer tokenizer = new StringTokenizer(typeNames, new String(new char[] {JavaElement.JEM_TYPE})); | |
type = cu.getType(tokenizer.nextToken()); | |
while (tokenizer.hasMoreTokens()) { | |
//deal with inner types | |
type= type.getType(tokenizer.nextToken()); | |
} | |
} | |
return type; | |
} | |
/** | |
* @see JavaElement#getHandleMemento() | |
*/ | |
public String getHandleMemento(){ | |
return getElementName(); | |
} | |
/** | |
* Returns the <code>char</code> that marks the start of this handles | |
* contribution to a memento. | |
*/ | |
protected char getHandleMementoDelimiter(){ | |
Assert.isTrue(false, Util.bind("assert.shouldNotImplement")); //$NON-NLS-1$ | |
return 0; | |
} | |
/** | |
* @see IJavaElement | |
*/ | |
public IJavaModel getJavaModel() { | |
return this; | |
} | |
/** | |
* @see IJavaElement | |
*/ | |
public IJavaProject getJavaProject() { | |
return null; | |
} | |
/** | |
* @see IJavaModel | |
*/ | |
public IJavaProject getJavaProject(String name) { | |
return new JavaProject(this.getWorkspace().getRoot().getProject(name), this); | |
} | |
/** | |
* Returns the active Java project associated with the specified | |
* resource, or <code>null</code> if no Java project yet exists | |
* for the resource. | |
* | |
* @exception IllegalArgumentException if the given resource | |
* is not one of an IProject, IFolder, or IFile. | |
*/ | |
public IJavaProject getJavaProject(IResource resource) { | |
if (resource.getType() == IResource.FOLDER) { | |
return new JavaProject(((IFolder)resource).getProject(), this); | |
} else if (resource.getType() == IResource.FILE) { | |
return new JavaProject(((IFile)resource).getProject(), this); | |
} else if (resource.getType() == IResource.PROJECT) { | |
return new JavaProject((IProject)resource, this); | |
} else { | |
throw new IllegalArgumentException(Util.bind("element.invalidResourceForProject")); //$NON-NLS-1$ | |
} | |
} | |
/** | |
* @see IJavaModel | |
*/ | |
public IJavaProject[] getJavaProjects() throws JavaModelException { | |
ArrayList list = getChildrenOfType(JAVA_PROJECT); | |
IJavaProject[] array= new IJavaProject[list.size()]; | |
list.toArray(array); | |
return array; | |
} | |
/* | |
* @see IJavaElement | |
*/ | |
public IPath getPath() { | |
return Path.ROOT; | |
} | |
/* | |
* @see IJavaElement | |
*/ | |
public IResource getResource() { | |
return ResourcesPlugin.getWorkspace().getRoot(); | |
} | |
/** | |
* @see IOpenable | |
*/ | |
public IResource getUnderlyingResource() throws JavaModelException { | |
return null; | |
} | |
/** | |
* Returns the workbench associated with this object. | |
*/ | |
public IWorkspace getWorkspace() { | |
return ResourcesPlugin.getWorkspace(); | |
} | |
/** | |
* @see IJavaModel | |
*/ | |
public void move(IJavaElement[] elements, IJavaElement[] containers, IJavaElement[] siblings, String[] renamings, boolean force, IProgressMonitor monitor) throws JavaModelException { | |
if (elements != null && elements[0] != null && elements[0].getElementType() < IJavaElement.TYPE) { | |
runOperation(new MoveResourceElementsOperation(elements, containers, force), elements, siblings, renamings, monitor); | |
} else { | |
runOperation(new MoveElementsOperation(elements, containers, force), elements, siblings, renamings, monitor); | |
} | |
} | |
/** | |
* @see IJavaModel | |
*/ | |
public void rename(IJavaElement[] elements, IJavaElement[] destinations, String[] renamings, boolean force, IProgressMonitor monitor) throws JavaModelException { | |
MultiOperation op; | |
if (elements != null && elements[0] != null && elements[0].getElementType() < IJavaElement.TYPE) { | |
op = new RenameResourceElementsOperation(elements, destinations, renamings, force); | |
} else { | |
op = new RenameElementsOperation(elements, destinations, renamings, force); | |
} | |
runOperation(op, monitor); | |
} | |
/* | |
* @see JavaElement#rootedAt(IJavaProject) | |
*/ | |
public IJavaElement rootedAt(IJavaProject project) { | |
return this; | |
} | |
/** | |
* Configures and runs the <code>MultiOperation</code>. | |
*/ | |
protected void runOperation(MultiOperation op, IJavaElement[] elements, IJavaElement[] siblings, String[] renamings, IProgressMonitor monitor) throws JavaModelException { | |
op.setRenamings(renamings); | |
if (siblings != null) { | |
for (int i = 0; i < elements.length; i++) { | |
op.setInsertBefore(elements[i], siblings[i]); | |
} | |
} | |
runOperation(op, monitor); | |
} | |
/** | |
* @private Debugging purposes | |
*/ | |
protected void toStringInfo(int tab, StringBuffer buffer, Object info) { | |
buffer.append(this.tabString(tab)); | |
buffer.append("Java Model"); //$NON-NLS-1$ | |
if (info == null) { | |
buffer.append(" (not open)"); //$NON-NLS-1$ | |
} | |
} | |
/** | |
* Flushes the cache of external files known to be existing. | |
*/ | |
public static void flushExternalFileCache() { | |
existingExternalFiles = new HashSet(); | |
} | |
/** | |
* Helper method - returns the targeted item (IResource if internal or java.io.File if external), | |
* or null if unbound | |
* Internal items must be referred to using container relative paths. | |
*/ | |
public static Object getTarget(IContainer container, IPath path, boolean checkResourceExistence) { | |
if (path == null) return null; | |
// lookup - inside the container | |
IResource resource = container.findMember(path); | |
if (resource != null){ | |
if (!checkResourceExistence ||resource.exists()) return resource; | |
return null; | |
} | |
// lookup - outside the container | |
File externalFile = new File(path.toOSString()); | |
if (!checkResourceExistence) { | |
return externalFile; | |
} else if (existingExternalFiles.contains(externalFile)) { | |
return externalFile; | |
} else { | |
if (JavaModelManager.ZIP_ACCESS_VERBOSE) { | |
System.out.println("[JavaModel.getTarget(...)] Checking existence of " + path.toString()); //$NON-NLS-1$ | |
} | |
if (externalFile.exists()) { | |
// cache external file | |
existingExternalFiles.add(externalFile); | |
return externalFile; | |
} | |
} | |
return null; | |
} | |
} |