1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.core;
14 import java.util.ArrayList;
15 import java.util.HashSet;
18 import net.sourceforge.phpdt.core.IJavaElement;
19 import net.sourceforge.phpdt.core.IJavaModel;
20 import net.sourceforge.phpdt.core.IJavaProject;
21 import net.sourceforge.phpdt.core.JavaModelException;
22 import net.sourceforge.phpdt.internal.core.util.Util;
24 import org.eclipse.core.resources.IContainer;
25 import org.eclipse.core.resources.IFile;
26 import org.eclipse.core.resources.IFolder;
27 import org.eclipse.core.resources.IProject;
28 import org.eclipse.core.resources.IResource;
29 import org.eclipse.core.resources.IWorkspace;
30 import org.eclipse.core.resources.ResourcesPlugin;
31 import org.eclipse.core.runtime.IPath;
32 import org.eclipse.core.runtime.IProgressMonitor;
33 import org.eclipse.core.runtime.Path;
34 import net.sourceforge.phpdt.internal.core.JavaModelInfo;
35 import net.sourceforge.phpdt.internal.core.JavaProject;
36 import net.sourceforge.phpdt.internal.core.OpenableElementInfo;
37 import org.eclipse.jface.util.Assert;
41 * Implementation of <code>IJavaModel<code>. The Java Model maintains a cache of
42 * active <code>IJavaProject</code>s in a workspace. A Java Model is specific to a
43 * workspace. To retrieve a workspace's model, use the
44 * <code>#getJavaModel(IWorkspace)</code> method.
48 public class JavaModel extends Openable implements IJavaModel {
51 * A set of java.io.Files used as a cache of external jars that
52 * are known to be existing.
53 * Note this cache is kept for the whole session.
55 public static HashSet existingExternalFiles = new HashSet();
58 * Constructs a new Java Model on the given workspace.
59 * Note that only one instance of JavaModel handle should ever be created.
60 * One should only indirect through JavaModelManager#getJavaModel() to get
63 * @exception Error if called more than once
65 protected JavaModel() throws Error {
66 super(null, "" /*workspace has empty name*/); //$NON-NLS-1$
68 protected boolean buildStructure(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) /*throws JavaModelException*/ {
70 // determine my children
71 IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
72 for (int i = 0, max = projects.length; i < max; i++) {
73 IProject project = projects[i];
74 if (JavaProject.hasJavaNature(project)) {
75 info.addChild(getJavaProject(project));
79 newElements.put(this, info);
86 public boolean contains(IResource resource) {
87 switch (resource.getType()) {
89 case IResource.PROJECT:
93 IJavaProject[] projects;
95 projects = this.getJavaProjects();
96 } catch (JavaModelException e) {
99 for (int i = 0, length = projects.length; i < length; i++) {
100 JavaProject project = (JavaProject)projects[i];
102 if (!project.contains(resource)) {
111 public void copy(IJavaElement[] elements, IJavaElement[] containers, IJavaElement[] siblings, String[] renamings, boolean force, IProgressMonitor monitor) throws JavaModelException {
112 if (elements != null && elements.length > 0 && elements[0] != null && elements[0].getElementType() < IJavaElement.TYPE) {
113 runOperation(new CopyResourceElementsOperation(elements, containers, force), elements, siblings, renamings, monitor);
115 runOperation(new CopyElementsOperation(elements, containers, force), elements, siblings, renamings, monitor);
119 * Returns a new element info for this element.
121 protected Object createElementInfo() {
122 return new JavaModelInfo();
128 public void delete(IJavaElement[] elements, boolean force, IProgressMonitor monitor) throws JavaModelException {
129 if (elements != null && elements.length > 0 && elements[0] != null && elements[0].getElementType() < IJavaElement.TYPE) {
130 runOperation(new DeleteResourceElementsOperation(elements, force), monitor);
132 runOperation(new DeleteElementsOperation(elements, force), monitor);
136 * Finds the given project in the list of the java model's children.
137 * Returns null if not found.
139 public IJavaProject findJavaProject(IProject project) {
141 IJavaProject[] projects = this.getOldJavaProjectsList();
142 for (int i = 0, length = projects.length; i < length; i++) {
143 IJavaProject javaProject = projects[i];
144 if (project.equals(javaProject.getProject())) {
148 } catch (JavaModelException e) {
155 public int getElementType() {
159 * Flushes the cache of external files known to be existing.
161 public static void flushExternalFileCache() {
162 existingExternalFiles = new HashSet();
167 protected boolean generateInfos(
168 OpenableElementInfo info,
171 IResource underlyingResource) throws JavaModelException {
173 JavaModelManager.getJavaModelManager().putInfo(this, info);
174 // determine my children
175 IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
176 for (int i = 0, max = projects.length; i < max; i++) {
177 IProject project = projects[i];
178 if (JavaProject.hasJavaNature(project)) {
179 info.addChild(getJavaProject(project));
185 * Returns the <code>IJavaElement</code> represented by the <code>String</code>
187 * @see getHandleMemento()
189 //protected IJavaElement getHandleFromMementoForBinaryMembers(String memento, IPackageFragmentRoot root, int rootEnd, int end) throws JavaModelException {
191 // //deal with class file and binary members
192 // IPackageFragment frag = null;
193 // if (rootEnd == end - 1) {
195 // frag= root.getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME);
197 // frag= root.getPackageFragment(memento.substring(rootEnd + 1, end));
200 // end = memento.indexOf(JavaElement.JEM_TYPE, oldEnd);
202 // //we ended with a class file
203 // return frag.getClassFile(memento.substring(oldEnd + 1));
205 // IClassFile cf = frag.getClassFile(memento.substring(oldEnd + 1, end));
207 // end = memento.indexOf(JavaElement.JEM_TYPE, oldEnd);
209 // end = memento.indexOf(JavaElement.JEM_FIELD, end);
212 // IType type = cf.getType();
213 // return type.getField(memento.substring(end + 1));
215 // end = memento.indexOf(JavaElement.JEM_METHOD, oldEnd);
219 // IType type = cf.getType();
220 // String methodName;
221 // end = memento.lastIndexOf(JavaElement.JEM_METHOD);
222 // String[] parameterTypes = null;
223 // if (end == oldEnd) {
224 // methodName = memento.substring(end + 1);
225 // //no parameter types
226 // parameterTypes = new String[] {};
228 // String parameters = memento.substring(oldEnd + 1);
229 // StringTokenizer tokenizer = new StringTokenizer(parameters, new String(new char[] {JavaElement.JEM_METHOD}));
230 // parameterTypes = new String[tokenizer.countTokens() - 1];
231 // methodName= tokenizer.nextToken();
233 // while (tokenizer.hasMoreTokens()) {
234 // parameterTypes[i] = tokenizer.nextToken();
238 // return type.getMethod(methodName, parameterTypes);
242 // return cf.getType();
245 * Returns the <code>IPackageFragmentRoot</code> represented by the <code>String</code>
247 * @see getHandleMemento()
249 //protected IPackageFragmentRoot getHandleFromMementoForRoot(String memento, JavaProject project, int projectEnd, int rootEnd) {
250 // String rootName = null;
251 // if (rootEnd == projectEnd - 1) {
253 // rootName = IPackageFragmentRoot.DEFAULT_PACKAGEROOT_PATH;
255 // rootName = memento.substring(projectEnd + 1, rootEnd);
257 // return project.getPackageFragmentRoot(new Path(rootName));
260 * Returns the <code>IJavaElement</code> represented by the <code>String</code>
262 * @see getHandleMemento()
264 //protected IJavaElement getHandleFromMementoForSourceMembers(String memento, IPackageFragmentRoot root, int rootEnd, int end) throws JavaModelException {
266 // //deal with compilation units and source members
267 // IPackageFragment frag = null;
268 // if (rootEnd == end - 1) {
270 // frag= root.getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME);
272 // frag= root.getPackageFragment(memento.substring(rootEnd + 1, end));
275 // end = memento.indexOf(JavaElement.JEM_PACKAGEDECLARATION, end);
277 // //package declaration
278 // ICompilationUnit cu = frag.getCompilationUnit(memento.substring(oldEnd + 1, end));
279 // return cu.getPackageDeclaration(memento.substring(end + 1));
281 // end = memento.indexOf(JavaElement.JEM_IMPORTDECLARATION, oldEnd);
283 // //import declaration
284 // ICompilationUnit cu = frag.getCompilationUnit(memento.substring(oldEnd + 1, end));
285 // return cu.getImport(memento.substring(end + 1));
287 // int typeStart = memento.indexOf(JavaElement.JEM_TYPE, oldEnd);
288 // if (typeStart == -1) {
289 // //we ended with a compilation unit
290 // return frag.getCompilationUnit(memento.substring(oldEnd + 1));
294 // ICompilationUnit cu = frag.getCompilationUnit(memento.substring(oldEnd + 1, typeStart));
295 // end = memento.indexOf(JavaElement.JEM_FIELD, oldEnd);
298 // IType type = getHandleFromMementoForSourceType(memento, cu, typeStart, end);
299 // return type.getField(memento.substring(end + 1));
301 // end = memento.indexOf(JavaElement.JEM_METHOD, oldEnd);
304 // IType type = getHandleFromMementoForSourceType(memento, cu, typeStart, end);
306 // String methodName;
307 // end = memento.lastIndexOf(JavaElement.JEM_METHOD);
308 // String[] parameterTypes = null;
309 // if (end == oldEnd) {
310 // methodName = memento.substring(end + 1);
311 // //no parameter types
312 // parameterTypes = new String[] {};
314 // String parameters = memento.substring(oldEnd + 1);
315 // StringTokenizer mTokenizer = new StringTokenizer(parameters, new String(new char[] {JavaElement.JEM_METHOD}));
316 // parameterTypes = new String[mTokenizer.countTokens() - 1];
317 // methodName = mTokenizer.nextToken();
319 // while (mTokenizer.hasMoreTokens()) {
320 // parameterTypes[i] = mTokenizer.nextToken();
324 // return type.getMethod(methodName, parameterTypes);
327 // end = memento.indexOf(JavaElement.JEM_INITIALIZER, oldEnd);
330 // IType type = getHandleFromMementoForSourceType(memento, cu, typeStart, end);
331 // return type.getInitializer(Integer.parseInt(memento.substring(end + 1)));
334 // return getHandleFromMementoForSourceType(memento, cu, typeStart, memento.length());
337 * Returns the <code>IJavaElement</code> represented by the <code>String</code>
339 * @see getHandleMemento()
341 //protected IType getHandleFromMementoForSourceType(String memento, ICompilationUnit cu, int typeStart, int typeEnd) throws JavaModelException {
342 // int end = memento.lastIndexOf(JavaElement.JEM_TYPE);
343 // IType type = null;
344 // if (end == typeStart) {
345 // String typeName = memento.substring(typeStart + 1, typeEnd);
346 // type = cu.getType(typeName);
349 // String typeNames = memento.substring(typeStart + 1, typeEnd);
350 // StringTokenizer tokenizer = new StringTokenizer(typeNames, new String(new char[] {JavaElement.JEM_TYPE}));
351 // type = cu.getType(tokenizer.nextToken());
352 // while (tokenizer.hasMoreTokens()) {
353 // //deal with inner types
354 // type= type.getType(tokenizer.nextToken());
362 * @see JavaElement#getHandleMemento()
364 public String getHandleMemento(){
365 return getElementName();
368 * Returns the <code>char</code> that marks the start of this handles
369 * contribution to a memento.
371 protected char getHandleMementoDelimiter(){
372 Assert.isTrue(false, "Should not be called"); //$NON-NLS-1$
378 public IJavaProject getJavaProject(String name) {
379 return new JavaProject(ResourcesPlugin.getWorkspace().getRoot().getProject(name), this);
382 * Returns the active Java project associated with the specified
383 * resource, or <code>null</code> if no Java project yet exists
386 * @exception IllegalArgumentException if the given resource
387 * is not one of an IProject, IFolder, or IFile.
389 public IJavaProject getJavaProject(IResource resource) {
390 switch(resource.getType()){
391 case IResource.FOLDER:
392 return new JavaProject(((IFolder)resource).getProject(), this);
394 return new JavaProject(((IFile)resource).getProject(), this);
395 case IResource.PROJECT:
396 return new JavaProject((IProject)resource, this);
398 throw new IllegalArgumentException(Util.bind("element.invalidResourceForProject")); //$NON-NLS-1$
404 public IJavaProject[] getJavaProjects() throws JavaModelException {
405 ArrayList list = getChildrenOfType(JAVA_PROJECT);
406 IJavaProject[] array= new IJavaProject[list.size()];
414 //public Object[] getNonJavaResources() throws JavaModelException {
415 // return ((JavaModelInfo) getElementInfo()).getNonJavaResources();
419 * Workaround for bug 15168 circular errors not reported
420 * Returns the list of java projects before resource delta processing
423 public IJavaProject[] getOldJavaProjectsList() throws JavaModelException {
424 JavaModelManager manager = JavaModelManager.getJavaModelManager();
426 manager.javaProjectsCache == null ?
427 this.getJavaProjects() :
428 manager.javaProjectsCache;
433 public IPath getPath() {
439 public IResource getResource() {
440 return ResourcesPlugin.getWorkspace().getRoot();
445 public IResource getUnderlyingResource() throws JavaModelException {
449 * Returns the workbench associated with this object.
451 public IWorkspace getWorkspace() {
452 return ResourcesPlugin.getWorkspace();
458 public void move(IJavaElement[] elements, IJavaElement[] containers, IJavaElement[] siblings, String[] renamings, boolean force, IProgressMonitor monitor) throws JavaModelException {
459 if (elements != null && elements.length > 0 && elements[0] != null && elements[0].getElementType() < IJavaElement.TYPE) {
460 runOperation(new MoveResourceElementsOperation(elements, containers, force), elements, siblings, renamings, monitor);
462 runOperation(new MoveElementsOperation(elements, containers, force), elements, siblings, renamings, monitor);
467 * @see IJavaModel#refreshExternalArchives(IJavaElement[], IProgressMonitor)
469 //public void refreshExternalArchives(IJavaElement[] elementsScope, IProgressMonitor monitor) throws JavaModelException {
470 // if (elementsScope == null){
471 // elementsScope = new IJavaElement[] { this };
473 // JavaModelManager.getJavaModelManager().deltaProcessor.checkExternalArchiveChanges(elementsScope, monitor);
479 public void rename(IJavaElement[] elements, IJavaElement[] destinations, String[] renamings, boolean force, IProgressMonitor monitor) throws JavaModelException {
481 if (elements != null && elements.length > 0 && elements[0] != null && elements[0].getElementType() < IJavaElement.TYPE) {
482 op = new RenameResourceElementsOperation(elements, destinations, renamings, force);
484 op = new RenameElementsOperation(elements, destinations, renamings, force);
487 runOperation(op, monitor);
490 * @see JavaElement#rootedAt(IJavaProject)
492 public IJavaElement rootedAt(IJavaProject project) {
497 * Configures and runs the <code>MultiOperation</code>.
499 protected void runOperation(MultiOperation op, IJavaElement[] elements, IJavaElement[] siblings, String[] renamings, IProgressMonitor monitor) throws JavaModelException {
500 op.setRenamings(renamings);
501 if (siblings != null) {
502 for (int i = 0; i < elements.length; i++) {
503 op.setInsertBefore(elements[i], siblings[i]);
506 // runOperation(op, monitor);
507 op.runOperation(monitor);
510 * @private Debugging purposes
512 protected void toStringInfo(int tab, StringBuffer buffer, Object info) {
513 buffer.append(this.tabString(tab));
514 buffer.append("Java Model"); //$NON-NLS-1$
516 buffer.append(" (not open)"); //$NON-NLS-1$
521 * Helper method - returns the targeted item (IResource if internal or java.io.File if external),
523 * Internal items must be referred to using container relative paths.
525 public static Object getTarget(IContainer container, IPath path, boolean checkResourceExistence) {
527 if (path == null) return null;
529 // lookup - inside the container
530 if (path.getDevice() == null) { // container relative paths should not contain a device
531 // (see http://dev.eclipse.org/bugs/show_bug.cgi?id=18684)
532 // (case of a workspace rooted at d:\ )
533 IResource resource = container.findMember(path);
534 if (resource != null){
535 if (!checkResourceExistence ||resource.exists()) return resource;
540 // if path is relative, it cannot be an external path
541 // (see http://dev.eclipse.org/bugs/show_bug.cgi?id=22517)
542 if (!path.isAbsolute()) return null;
544 // lookup - outside the container
545 File externalFile = new File(path.toOSString());
546 if (!checkResourceExistence) {
548 } else if (existingExternalFiles.contains(externalFile)) {
551 if (JavaModelManager.ZIP_ACCESS_VERBOSE) {
552 System.out.println("(" + Thread.currentThread() + ") [JavaModel.getTarget(...)] Checking existence of " + path.toString()); //$NON-NLS-1$ //$NON-NLS-2$
554 if (externalFile.exists()) {
555 // cache external file
556 existingExternalFiles.add(externalFile);