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.IOpenable;
22 import net.sourceforge.phpdt.core.JavaModelException;
23 import net.sourceforge.phpdt.core.WorkingCopyOwner;
24 import net.sourceforge.phpdt.internal.core.util.MementoTokenizer;
25 import net.sourceforge.phpdt.internal.core.util.Util;
27 import org.eclipse.core.resources.IContainer;
28 import org.eclipse.core.resources.IFile;
29 import org.eclipse.core.resources.IFolder;
30 import org.eclipse.core.resources.IProject;
31 import org.eclipse.core.resources.IResource;
32 import org.eclipse.core.resources.IWorkspace;
33 import org.eclipse.core.resources.ResourcesPlugin;
34 import org.eclipse.core.runtime.IPath;
35 import org.eclipse.core.runtime.IProgressMonitor;
36 import org.eclipse.core.runtime.Path;
38 //import org.eclipse.jface.text.Assert;
39 import org.eclipse.core.runtime.Assert;
42 * Implementation of <code>IJavaModel<code>. The Java Model maintains a cache of
43 * active <code>IJavaProject</code>s in a workspace. A Java Model is specific to a
44 * workspace. To retrieve a workspace's model, use the
45 * <code>#getJavaModel(IWorkspace)</code> method.
49 public class JavaModel extends Openable implements IJavaModel {
52 * A set of java.io.Files used as a cache of external jars that are known to
53 * be existing. 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. Note that only one
59 * instance of JavaModel handle should ever be created. One should only
60 * indirect through JavaModelManager#getJavaModel() to get access to it.
63 * if called more than once
65 protected JavaModel() throws Error {
66 super(null, "" /* workspace has empty name */); //$NON-NLS-1$
69 protected boolean buildStructure(OpenableElementInfo info,
70 IProgressMonitor pm, Map newElements, IResource underlyingResource) /*
75 // determine my children
76 IProject[] projects = ResourcesPlugin.getWorkspace().getRoot()
78 for (int i = 0, max = projects.length; i < max; i++) {
79 IProject project = projects[i];
80 if (JavaProject.hasJavaNature(project)) {
81 info.addChild(getJavaProject(project));
85 newElements.put(this, info);
93 public boolean contains(IResource resource) {
94 switch (resource.getType()) {
96 case IResource.PROJECT:
100 IJavaProject[] projects;
102 projects = this.getJavaProjects();
103 } catch (JavaModelException e) {
106 for (int i = 0, length = projects.length; i < length; i++) {
107 JavaProject project = (JavaProject) projects[i];
109 if (!project.contains(resource)) {
119 public void copy(IJavaElement[] elements, IJavaElement[] containers,
120 IJavaElement[] siblings, String[] renamings, boolean force,
121 IProgressMonitor monitor) throws JavaModelException {
122 if (elements != null && elements.length > 0 && elements[0] != null
123 && elements[0].getElementType() < IJavaElement.TYPE) {
124 runOperation(new CopyResourceElementsOperation(elements,
125 containers, force), elements, siblings, renamings, monitor);
128 new CopyElementsOperation(elements, containers, force),
129 elements, siblings, renamings, monitor);
134 * Returns a new element info for this element.
136 protected Object createElementInfo() {
137 return new JavaModelInfo();
143 public void delete(IJavaElement[] elements, boolean force,
144 IProgressMonitor monitor) throws JavaModelException {
145 if (elements != null && elements.length > 0 && elements[0] != null
146 && elements[0].getElementType() < IJavaElement.TYPE) {
147 runOperation(new DeleteResourceElementsOperation(elements, force),
150 runOperation(new DeleteElementsOperation(elements, force), monitor);
155 * Finds the given project in the list of the java model's children. Returns
158 public IJavaProject findJavaProject(IProject project) {
160 IJavaProject[] projects = this.getOldJavaProjectsList();
161 for (int i = 0, length = projects.length; i < length; i++) {
162 IJavaProject javaProject = projects[i];
163 if (project.equals(javaProject.getProject())) {
167 } catch (JavaModelException e) {
175 public int getElementType() {
180 * Flushes the cache of external files known to be existing.
182 public static void flushExternalFileCache() {
183 existingExternalFiles = new HashSet();
188 protected boolean generateInfos(OpenableElementInfo info,
189 IProgressMonitor pm, Map newElements, IResource underlyingResource)
190 throws JavaModelException {
192 JavaModelManager.getJavaModelManager().putInfo(this, info);
193 // determine my children
194 IProject[] projects = ResourcesPlugin.getWorkspace().getRoot()
196 for (int i = 0, max = projects.length; i < max; i++) {
197 IProject project = projects[i];
198 if (JavaProject.hasJavaNature(project)) {
199 info.addChild(getJavaProject(project));
206 * Returns the <code>IJavaElement</code> represented by the
207 * <code>String</code> memento.
209 * @see getHandleMemento()
211 // protected IJavaElement getHandleFromMementoForBinaryMembers(String
212 // memento, IPackageFragmentRoot root, int rootEnd, int end) throws
213 // JavaModelException {
215 // //deal with class file and binary members
216 // IPackageFragment frag = null;
217 // if (rootEnd == end - 1) {
219 // frag= root.getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME);
221 // frag= root.getPackageFragment(memento.substring(rootEnd + 1, end));
224 // end = memento.indexOf(JavaElement.JEM_TYPE, oldEnd);
226 // //we ended with a class file
227 // return frag.getClassFile(memento.substring(oldEnd + 1));
229 // IClassFile cf = frag.getClassFile(memento.substring(oldEnd + 1, end));
231 // end = memento.indexOf(JavaElement.JEM_TYPE, oldEnd);
233 // end = memento.indexOf(JavaElement.JEM_FIELD, end);
236 // IType type = cf.getType();
237 // return type.getField(memento.substring(end + 1));
239 // end = memento.indexOf(JavaElement.JEM_METHOD, oldEnd);
243 // IType type = cf.getType();
244 // String methodName;
245 // end = memento.lastIndexOf(JavaElement.JEM_METHOD);
246 // String[] parameterTypes = null;
247 // if (end == oldEnd) {
248 // methodName = memento.substring(end + 1);
249 // //no parameter types
250 // parameterTypes = new String[] {};
252 // String parameters = memento.substring(oldEnd + 1);
253 // StringTokenizer tokenizer = new StringTokenizer(parameters, new
254 // String(new char[] {JavaElement.JEM_METHOD}));
255 // parameterTypes = new String[tokenizer.countTokens() - 1];
256 // methodName= tokenizer.nextToken();
258 // while (tokenizer.hasMoreTokens()) {
259 // parameterTypes[i] = tokenizer.nextToken();
263 // return type.getMethod(methodName, parameterTypes);
267 // return cf.getType();
270 * Returns the <code>IPackageFragmentRoot</code> represented by the
271 * <code>String</code> memento.
273 * @see getHandleMemento()
275 // protected IPackageFragmentRoot getHandleFromMementoForRoot(String
276 // memento, JavaProject project, int projectEnd, int rootEnd) {
277 // String rootName = null;
278 // if (rootEnd == projectEnd - 1) {
280 // rootName = IPackageFragmentRoot.DEFAULT_PACKAGEROOT_PATH;
282 // rootName = memento.substring(projectEnd + 1, rootEnd);
284 // return project.getPackageFragmentRoot(new Path(rootName));
287 * Returns the <code>IJavaElement</code> represented by the
288 * <code>String</code> memento.
290 * @see getHandleMemento()
292 // protected IJavaElement getHandleFromMementoForSourceMembers(String
293 // memento, IPackageFragmentRoot root, int rootEnd, int end) throws
294 // JavaModelException {
296 // //deal with compilation units and source members
297 // IPackageFragment frag = null;
298 // if (rootEnd == end - 1) {
300 // frag= root.getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME);
302 // frag= root.getPackageFragment(memento.substring(rootEnd + 1, end));
305 // end = memento.indexOf(JavaElement.JEM_PACKAGEDECLARATION, end);
307 // //package declaration
308 // ICompilationUnit cu = frag.getCompilationUnit(memento.substring(oldEnd +
310 // return cu.getPackageDeclaration(memento.substring(end + 1));
312 // end = memento.indexOf(JavaElement.JEM_IMPORTDECLARATION, oldEnd);
314 // //import declaration
315 // ICompilationUnit cu = frag.getCompilationUnit(memento.substring(oldEnd +
317 // return cu.getImport(memento.substring(end + 1));
319 // int typeStart = memento.indexOf(JavaElement.JEM_TYPE, oldEnd);
320 // if (typeStart == -1) {
321 // //we ended with a compilation unit
322 // return frag.getCompilationUnit(memento.substring(oldEnd + 1));
326 // ICompilationUnit cu = frag.getCompilationUnit(memento.substring(oldEnd +
328 // end = memento.indexOf(JavaElement.JEM_FIELD, oldEnd);
331 // IType type = getHandleFromMementoForSourceType(memento, cu, typeStart,
333 // return type.getField(memento.substring(end + 1));
335 // end = memento.indexOf(JavaElement.JEM_METHOD, oldEnd);
338 // IType type = getHandleFromMementoForSourceType(memento, cu, typeStart,
341 // String methodName;
342 // end = memento.lastIndexOf(JavaElement.JEM_METHOD);
343 // String[] parameterTypes = null;
344 // if (end == oldEnd) {
345 // methodName = memento.substring(end + 1);
346 // //no parameter types
347 // parameterTypes = new String[] {};
349 // String parameters = memento.substring(oldEnd + 1);
350 // StringTokenizer mTokenizer = new StringTokenizer(parameters, new
351 // String(new char[] {JavaElement.JEM_METHOD}));
352 // parameterTypes = new String[mTokenizer.countTokens() - 1];
353 // methodName = mTokenizer.nextToken();
355 // while (mTokenizer.hasMoreTokens()) {
356 // parameterTypes[i] = mTokenizer.nextToken();
360 // return type.getMethod(methodName, parameterTypes);
363 // end = memento.indexOf(JavaElement.JEM_INITIALIZER, oldEnd);
366 // IType type = getHandleFromMementoForSourceType(memento, cu, typeStart,
368 // return type.getInitializer(Integer.parseInt(memento.substring(end + 1)));
371 // return getHandleFromMementoForSourceType(memento, cu, typeStart,
372 // memento.length());
375 * Returns the <code>IJavaElement</code> represented by the
376 * <code>String</code> memento.
378 * @see getHandleMemento()
380 // protected IType getHandleFromMementoForSourceType(String memento,
381 // ICompilationUnit cu, int typeStart, int typeEnd) throws
382 // JavaModelException {
383 // int end = memento.lastIndexOf(JavaElement.JEM_TYPE);
384 // IType type = null;
385 // if (end == typeStart) {
386 // String typeName = memento.substring(typeStart + 1, typeEnd);
387 // type = cu.getType(typeName);
390 // String typeNames = memento.substring(typeStart + 1, typeEnd);
391 // StringTokenizer tokenizer = new StringTokenizer(typeNames, new String(new
392 // char[] {JavaElement.JEM_TYPE}));
393 // type = cu.getType(tokenizer.nextToken());
394 // while (tokenizer.hasMoreTokens()) {
395 // //deal with inner types
396 // type= type.getType(tokenizer.nextToken());
405 public IJavaElement getHandleFromMemento(String token,
406 MementoTokenizer memento, WorkingCopyOwner owner) {
407 switch (token.charAt(0)) {
409 return getHandleUpdatingCountFromMemento(memento, owner);
410 case JEM_JAVAPROJECT:
411 String projectName = memento.nextToken();
412 JavaElement project = (JavaElement) getJavaProject(projectName);
413 return project.getHandleFromMemento(memento, owner);
419 * @see JavaElement#getHandleMemento()
421 public String getHandleMemento() {
422 return getElementName();
426 * Returns the <code>char</code> that marks the start of this handles
427 * contribution to a memento.
429 protected char getHandleMementoDelimiter() {
430 Assert.isTrue(false, "Should not be called"); //$NON-NLS-1$
437 public IJavaProject getJavaProject(String name) {
438 return new JavaProject(ResourcesPlugin.getWorkspace().getRoot()
439 .getProject(name), this);
443 * Returns the active Java project associated with the specified resource,
444 * or <code>null</code> if no Java project yet exists for the resource.
446 * @exception IllegalArgumentException
447 * if the given resource is not one of an IProject, IFolder,
450 public IJavaProject getJavaProject(IResource resource) {
451 switch (resource.getType()) {
452 case IResource.FOLDER:
453 return new JavaProject(((IFolder) resource).getProject(), this);
455 return new JavaProject(((IFile) resource).getProject(), this);
456 case IResource.PROJECT:
457 return new JavaProject((IProject) resource, this);
459 throw new IllegalArgumentException(Util
460 .bind("element.invalidResourceForProject")); //$NON-NLS-1$
467 public IJavaProject[] getJavaProjects() throws JavaModelException {
468 ArrayList list = getChildrenOfType(JAVA_PROJECT);
469 IJavaProject[] array = new IJavaProject[list.size()];
478 // public Object[] getNonJavaResources() throws JavaModelException {
479 // return ((JavaModelInfo) getElementInfo()).getNonJavaResources();
483 * Workaround for bug 15168 circular errors not reported Returns the list of
484 * java projects before resource delta processing has started.
486 public IJavaProject[] getOldJavaProjectsList() throws JavaModelException {
487 JavaModelManager manager = JavaModelManager.getJavaModelManager();
488 return manager.javaProjectsCache == null ? this.getJavaProjects()
489 : manager.javaProjectsCache;
495 public IPath getPath() {
502 public IResource getResource() {
503 return ResourcesPlugin.getWorkspace().getRoot();
509 public IResource getUnderlyingResource() throws JavaModelException {
514 * Returns the workbench associated with this object.
516 public IWorkspace getWorkspace() {
517 return ResourcesPlugin.getWorkspace();
523 public void move(IJavaElement[] elements, IJavaElement[] containers,
524 IJavaElement[] siblings, String[] renamings, boolean force,
525 IProgressMonitor monitor) throws JavaModelException {
526 if (elements != null && elements.length > 0 && elements[0] != null
527 && elements[0].getElementType() < IJavaElement.TYPE) {
528 runOperation(new MoveResourceElementsOperation(elements,
529 containers, force), elements, siblings, renamings, monitor);
532 new MoveElementsOperation(elements, containers, force),
533 elements, siblings, renamings, monitor);
538 * @see IJavaModel#refreshExternalArchives(IJavaElement[], IProgressMonitor)
540 // public void refreshExternalArchives(IJavaElement[] elementsScope,
541 // IProgressMonitor monitor) throws JavaModelException {
542 // if (elementsScope == null){
543 // elementsScope = new IJavaElement[] { this };
545 // JavaModelManager.getJavaModelManager().deltaProcessor.checkExternalArchiveChanges(elementsScope,
551 public void rename(IJavaElement[] elements, IJavaElement[] destinations,
552 String[] renamings, boolean force, IProgressMonitor monitor)
553 throws JavaModelException {
555 if (elements != null && elements.length > 0 && elements[0] != null
556 && elements[0].getElementType() < IJavaElement.TYPE) {
557 op = new RenameResourceElementsOperation(elements, destinations,
560 op = new RenameElementsOperation(elements, destinations, renamings,
564 runOperation(op, monitor);
568 * @see JavaElement#rootedAt(IJavaProject)
570 public IJavaElement rootedAt(IJavaProject project) {
576 * Configures and runs the <code>MultiOperation</code>.
578 protected void runOperation(MultiOperation op, IJavaElement[] elements,
579 IJavaElement[] siblings, String[] renamings,
580 IProgressMonitor monitor) throws JavaModelException {
581 op.setRenamings(renamings);
582 if (siblings != null) {
583 for (int i = 0; i < elements.length; i++) {
584 op.setInsertBefore(elements[i], siblings[i]);
587 // runOperation(op, monitor);
588 op.runOperation(monitor);
592 * @private Debugging purposes
594 protected void toStringInfo(int tab, StringBuffer buffer, Object info) {
595 buffer.append(this.tabString(tab));
596 buffer.append("Java Model"); //$NON-NLS-1$
598 buffer.append(" (not open)"); //$NON-NLS-1$
603 * Helper method - returns the targeted item (IResource if internal or
604 * java.io.File if external), or null if unbound Internal items must be
605 * referred to using container relative paths.
607 public static Object getTarget(IContainer container, IPath path,
608 boolean checkResourceExistence) {
613 // lookup - inside the container
614 if (path.getDevice() == null) { // container relative paths should not
616 // (see http://dev.eclipse.org/bugs/show_bug.cgi?id=18684)
617 // (case of a workspace rooted at d:\ )
618 IResource resource = container.findMember(path);
619 if (resource != null) {
620 if (!checkResourceExistence || resource.exists())
626 // if path is relative, it cannot be an external path
627 // (see http://dev.eclipse.org/bugs/show_bug.cgi?id=22517)
628 if (!path.isAbsolute())
631 // lookup - outside the container
632 File externalFile = new File(path.toOSString());
633 if (!checkResourceExistence) {
635 } else if (existingExternalFiles.contains(externalFile)) {
638 if (JavaModelManager.ZIP_ACCESS_VERBOSE) {
640 .println("(" + Thread.currentThread() + ") [JavaModel.getTarget(...)] Checking existence of " + path.toString()); //$NON-NLS-1$ //$NON-NLS-2$
642 if (externalFile.exists()) {
643 // cache external file
644 existingExternalFiles.add(externalFile);