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;
37 import org.eclipse.jface.util.Assert;
40 * Implementation of <code>IJavaModel<code>. The Java Model maintains a cache of
41 * active <code>IJavaProject</code>s in a workspace. A Java Model is specific to a
42 * workspace. To retrieve a workspace's model, use the
43 * <code>#getJavaModel(IWorkspace)</code> method.
47 public class JavaModel extends Openable implements IJavaModel {
50 * A set of java.io.Files used as a cache of external jars that are known to
51 * be existing. Note this cache is kept for the whole session.
53 public static HashSet existingExternalFiles = new HashSet();
56 * Constructs a new Java Model on the given workspace. Note that only one
57 * instance of JavaModel handle should ever be created. One should only
58 * indirect through JavaModelManager#getJavaModel() to get access to it.
61 * if called more than once
63 protected JavaModel() throws Error {
64 super(null, "" /* workspace has empty name */); //$NON-NLS-1$
67 protected boolean buildStructure(OpenableElementInfo info,
68 IProgressMonitor pm, Map newElements, IResource underlyingResource) /*
73 // determine my children
74 IProject[] projects = ResourcesPlugin.getWorkspace().getRoot()
76 for (int i = 0, max = projects.length; i < max; i++) {
77 IProject project = projects[i];
78 if (JavaProject.hasJavaNature(project)) {
79 info.addChild(getJavaProject(project));
83 newElements.put(this, info);
91 public boolean contains(IResource resource) {
92 switch (resource.getType()) {
94 case IResource.PROJECT:
98 IJavaProject[] projects;
100 projects = this.getJavaProjects();
101 } catch (JavaModelException e) {
104 for (int i = 0, length = projects.length; i < length; i++) {
105 JavaProject project = (JavaProject) projects[i];
107 if (!project.contains(resource)) {
117 public void copy(IJavaElement[] elements, IJavaElement[] containers,
118 IJavaElement[] siblings, String[] renamings, boolean force,
119 IProgressMonitor monitor) throws JavaModelException {
120 if (elements != null && elements.length > 0 && elements[0] != null
121 && elements[0].getElementType() < IJavaElement.TYPE) {
122 runOperation(new CopyResourceElementsOperation(elements,
123 containers, force), elements, siblings, renamings, monitor);
126 new CopyElementsOperation(elements, containers, force),
127 elements, siblings, renamings, monitor);
132 * Returns a new element info for this element.
134 protected Object createElementInfo() {
135 return new JavaModelInfo();
141 public void delete(IJavaElement[] elements, boolean force,
142 IProgressMonitor monitor) throws JavaModelException {
143 if (elements != null && elements.length > 0 && elements[0] != null
144 && elements[0].getElementType() < IJavaElement.TYPE) {
145 runOperation(new DeleteResourceElementsOperation(elements, force),
148 runOperation(new DeleteElementsOperation(elements, force), monitor);
153 * Finds the given project in the list of the java model's children. Returns
156 public IJavaProject findJavaProject(IProject project) {
158 IJavaProject[] projects = this.getOldJavaProjectsList();
159 for (int i = 0, length = projects.length; i < length; i++) {
160 IJavaProject javaProject = projects[i];
161 if (project.equals(javaProject.getProject())) {
165 } catch (JavaModelException e) {
173 public int getElementType() {
178 * Flushes the cache of external files known to be existing.
180 public static void flushExternalFileCache() {
181 existingExternalFiles = new HashSet();
186 protected boolean generateInfos(OpenableElementInfo info,
187 IProgressMonitor pm, Map newElements, IResource underlyingResource)
188 throws JavaModelException {
190 JavaModelManager.getJavaModelManager().putInfo(this, info);
191 // determine my children
192 IProject[] projects = ResourcesPlugin.getWorkspace().getRoot()
194 for (int i = 0, max = projects.length; i < max; i++) {
195 IProject project = projects[i];
196 if (JavaProject.hasJavaNature(project)) {
197 info.addChild(getJavaProject(project));
204 * Returns the <code>IJavaElement</code> represented by the
205 * <code>String</code> memento.
207 * @see getHandleMemento()
209 // protected IJavaElement getHandleFromMementoForBinaryMembers(String
210 // memento, IPackageFragmentRoot root, int rootEnd, int end) throws
211 // JavaModelException {
213 // //deal with class file and binary members
214 // IPackageFragment frag = null;
215 // if (rootEnd == end - 1) {
217 // frag= root.getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME);
219 // frag= root.getPackageFragment(memento.substring(rootEnd + 1, end));
222 // end = memento.indexOf(JavaElement.JEM_TYPE, oldEnd);
224 // //we ended with a class file
225 // return frag.getClassFile(memento.substring(oldEnd + 1));
227 // IClassFile cf = frag.getClassFile(memento.substring(oldEnd + 1, end));
229 // end = memento.indexOf(JavaElement.JEM_TYPE, oldEnd);
231 // end = memento.indexOf(JavaElement.JEM_FIELD, end);
234 // IType type = cf.getType();
235 // return type.getField(memento.substring(end + 1));
237 // end = memento.indexOf(JavaElement.JEM_METHOD, oldEnd);
241 // IType type = cf.getType();
242 // String methodName;
243 // end = memento.lastIndexOf(JavaElement.JEM_METHOD);
244 // String[] parameterTypes = null;
245 // if (end == oldEnd) {
246 // methodName = memento.substring(end + 1);
247 // //no parameter types
248 // parameterTypes = new String[] {};
250 // String parameters = memento.substring(oldEnd + 1);
251 // StringTokenizer tokenizer = new StringTokenizer(parameters, new
252 // String(new char[] {JavaElement.JEM_METHOD}));
253 // parameterTypes = new String[tokenizer.countTokens() - 1];
254 // methodName= tokenizer.nextToken();
256 // while (tokenizer.hasMoreTokens()) {
257 // parameterTypes[i] = tokenizer.nextToken();
261 // return type.getMethod(methodName, parameterTypes);
265 // return cf.getType();
268 * Returns the <code>IPackageFragmentRoot</code> represented by the
269 * <code>String</code> memento.
271 * @see getHandleMemento()
273 // protected IPackageFragmentRoot getHandleFromMementoForRoot(String
274 // memento, JavaProject project, int projectEnd, int rootEnd) {
275 // String rootName = null;
276 // if (rootEnd == projectEnd - 1) {
278 // rootName = IPackageFragmentRoot.DEFAULT_PACKAGEROOT_PATH;
280 // rootName = memento.substring(projectEnd + 1, rootEnd);
282 // return project.getPackageFragmentRoot(new Path(rootName));
285 * Returns the <code>IJavaElement</code> represented by the
286 * <code>String</code> memento.
288 * @see getHandleMemento()
290 // protected IJavaElement getHandleFromMementoForSourceMembers(String
291 // memento, IPackageFragmentRoot root, int rootEnd, int end) throws
292 // JavaModelException {
294 // //deal with compilation units and source members
295 // IPackageFragment frag = null;
296 // if (rootEnd == end - 1) {
298 // frag= root.getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME);
300 // frag= root.getPackageFragment(memento.substring(rootEnd + 1, end));
303 // end = memento.indexOf(JavaElement.JEM_PACKAGEDECLARATION, end);
305 // //package declaration
306 // ICompilationUnit cu = frag.getCompilationUnit(memento.substring(oldEnd +
308 // return cu.getPackageDeclaration(memento.substring(end + 1));
310 // end = memento.indexOf(JavaElement.JEM_IMPORTDECLARATION, oldEnd);
312 // //import declaration
313 // ICompilationUnit cu = frag.getCompilationUnit(memento.substring(oldEnd +
315 // return cu.getImport(memento.substring(end + 1));
317 // int typeStart = memento.indexOf(JavaElement.JEM_TYPE, oldEnd);
318 // if (typeStart == -1) {
319 // //we ended with a compilation unit
320 // return frag.getCompilationUnit(memento.substring(oldEnd + 1));
324 // ICompilationUnit cu = frag.getCompilationUnit(memento.substring(oldEnd +
326 // end = memento.indexOf(JavaElement.JEM_FIELD, oldEnd);
329 // IType type = getHandleFromMementoForSourceType(memento, cu, typeStart,
331 // return type.getField(memento.substring(end + 1));
333 // end = memento.indexOf(JavaElement.JEM_METHOD, oldEnd);
336 // IType type = getHandleFromMementoForSourceType(memento, cu, typeStart,
339 // String methodName;
340 // end = memento.lastIndexOf(JavaElement.JEM_METHOD);
341 // String[] parameterTypes = null;
342 // if (end == oldEnd) {
343 // methodName = memento.substring(end + 1);
344 // //no parameter types
345 // parameterTypes = new String[] {};
347 // String parameters = memento.substring(oldEnd + 1);
348 // StringTokenizer mTokenizer = new StringTokenizer(parameters, new
349 // String(new char[] {JavaElement.JEM_METHOD}));
350 // parameterTypes = new String[mTokenizer.countTokens() - 1];
351 // methodName = mTokenizer.nextToken();
353 // while (mTokenizer.hasMoreTokens()) {
354 // parameterTypes[i] = mTokenizer.nextToken();
358 // return type.getMethod(methodName, parameterTypes);
361 // end = memento.indexOf(JavaElement.JEM_INITIALIZER, oldEnd);
364 // IType type = getHandleFromMementoForSourceType(memento, cu, typeStart,
366 // return type.getInitializer(Integer.parseInt(memento.substring(end + 1)));
369 // return getHandleFromMementoForSourceType(memento, cu, typeStart,
370 // memento.length());
373 * Returns the <code>IJavaElement</code> represented by the
374 * <code>String</code> memento.
376 * @see getHandleMemento()
378 // protected IType getHandleFromMementoForSourceType(String memento,
379 // ICompilationUnit cu, int typeStart, int typeEnd) throws
380 // JavaModelException {
381 // int end = memento.lastIndexOf(JavaElement.JEM_TYPE);
382 // IType type = null;
383 // if (end == typeStart) {
384 // String typeName = memento.substring(typeStart + 1, typeEnd);
385 // type = cu.getType(typeName);
388 // String typeNames = memento.substring(typeStart + 1, typeEnd);
389 // StringTokenizer tokenizer = new StringTokenizer(typeNames, new String(new
390 // char[] {JavaElement.JEM_TYPE}));
391 // type = cu.getType(tokenizer.nextToken());
392 // while (tokenizer.hasMoreTokens()) {
393 // //deal with inner types
394 // type= type.getType(tokenizer.nextToken());
403 public IJavaElement getHandleFromMemento(String token,
404 MementoTokenizer memento, WorkingCopyOwner owner) {
405 switch (token.charAt(0)) {
407 return getHandleUpdatingCountFromMemento(memento, owner);
408 case JEM_JAVAPROJECT:
409 String projectName = memento.nextToken();
410 JavaElement project = (JavaElement) getJavaProject(projectName);
411 return project.getHandleFromMemento(memento, owner);
417 * @see JavaElement#getHandleMemento()
419 public String getHandleMemento() {
420 return getElementName();
424 * Returns the <code>char</code> that marks the start of this handles
425 * contribution to a memento.
427 protected char getHandleMementoDelimiter() {
428 Assert.isTrue(false, "Should not be called"); //$NON-NLS-1$
435 public IJavaProject getJavaProject(String name) {
436 return new JavaProject(ResourcesPlugin.getWorkspace().getRoot()
437 .getProject(name), this);
441 * Returns the active Java project associated with the specified resource,
442 * or <code>null</code> if no Java project yet exists for the resource.
444 * @exception IllegalArgumentException
445 * if the given resource is not one of an IProject, IFolder,
448 public IJavaProject getJavaProject(IResource resource) {
449 switch (resource.getType()) {
450 case IResource.FOLDER:
451 return new JavaProject(((IFolder) resource).getProject(), this);
453 return new JavaProject(((IFile) resource).getProject(), this);
454 case IResource.PROJECT:
455 return new JavaProject((IProject) resource, this);
457 throw new IllegalArgumentException(Util
458 .bind("element.invalidResourceForProject")); //$NON-NLS-1$
465 public IJavaProject[] getJavaProjects() throws JavaModelException {
466 ArrayList list = getChildrenOfType(JAVA_PROJECT);
467 IJavaProject[] array = new IJavaProject[list.size()];
476 // public Object[] getNonJavaResources() throws JavaModelException {
477 // return ((JavaModelInfo) getElementInfo()).getNonJavaResources();
481 * Workaround for bug 15168 circular errors not reported Returns the list of
482 * java projects before resource delta processing has started.
484 public IJavaProject[] getOldJavaProjectsList() throws JavaModelException {
485 JavaModelManager manager = JavaModelManager.getJavaModelManager();
486 return manager.javaProjectsCache == null ? this.getJavaProjects()
487 : manager.javaProjectsCache;
493 public IPath getPath() {
500 public IResource getResource() {
501 return ResourcesPlugin.getWorkspace().getRoot();
507 public IResource getUnderlyingResource() throws JavaModelException {
512 * Returns the workbench associated with this object.
514 public IWorkspace getWorkspace() {
515 return ResourcesPlugin.getWorkspace();
521 public void move(IJavaElement[] elements, IJavaElement[] containers,
522 IJavaElement[] siblings, String[] renamings, boolean force,
523 IProgressMonitor monitor) throws JavaModelException {
524 if (elements != null && elements.length > 0 && elements[0] != null
525 && elements[0].getElementType() < IJavaElement.TYPE) {
526 runOperation(new MoveResourceElementsOperation(elements,
527 containers, force), elements, siblings, renamings, monitor);
530 new MoveElementsOperation(elements, containers, force),
531 elements, siblings, renamings, monitor);
536 * @see IJavaModel#refreshExternalArchives(IJavaElement[], IProgressMonitor)
538 // public void refreshExternalArchives(IJavaElement[] elementsScope,
539 // IProgressMonitor monitor) throws JavaModelException {
540 // if (elementsScope == null){
541 // elementsScope = new IJavaElement[] { this };
543 // JavaModelManager.getJavaModelManager().deltaProcessor.checkExternalArchiveChanges(elementsScope,
549 public void rename(IJavaElement[] elements, IJavaElement[] destinations,
550 String[] renamings, boolean force, IProgressMonitor monitor)
551 throws JavaModelException {
553 if (elements != null && elements.length > 0 && elements[0] != null
554 && elements[0].getElementType() < IJavaElement.TYPE) {
555 op = new RenameResourceElementsOperation(elements, destinations,
558 op = new RenameElementsOperation(elements, destinations, renamings,
562 runOperation(op, monitor);
566 * @see JavaElement#rootedAt(IJavaProject)
568 public IJavaElement rootedAt(IJavaProject project) {
574 * Configures and runs the <code>MultiOperation</code>.
576 protected void runOperation(MultiOperation op, IJavaElement[] elements,
577 IJavaElement[] siblings, String[] renamings,
578 IProgressMonitor monitor) throws JavaModelException {
579 op.setRenamings(renamings);
580 if (siblings != null) {
581 for (int i = 0; i < elements.length; i++) {
582 op.setInsertBefore(elements[i], siblings[i]);
585 // runOperation(op, monitor);
586 op.runOperation(monitor);
590 * @private Debugging purposes
592 protected void toStringInfo(int tab, StringBuffer buffer, Object info) {
593 buffer.append(this.tabString(tab));
594 buffer.append("Java Model"); //$NON-NLS-1$
596 buffer.append(" (not open)"); //$NON-NLS-1$
601 * Helper method - returns the targeted item (IResource if internal or
602 * java.io.File if external), or null if unbound Internal items must be
603 * referred to using container relative paths.
605 public static Object getTarget(IContainer container, IPath path,
606 boolean checkResourceExistence) {
611 // lookup - inside the container
612 if (path.getDevice() == null) { // container relative paths should not
614 // (see http://dev.eclipse.org/bugs/show_bug.cgi?id=18684)
615 // (case of a workspace rooted at d:\ )
616 IResource resource = container.findMember(path);
617 if (resource != null) {
618 if (!checkResourceExistence || resource.exists())
624 // if path is relative, it cannot be an external path
625 // (see http://dev.eclipse.org/bugs/show_bug.cgi?id=22517)
626 if (!path.isAbsolute())
629 // lookup - outside the container
630 File externalFile = new File(path.toOSString());
631 if (!checkResourceExistence) {
633 } else if (existingExternalFiles.contains(externalFile)) {
636 if (JavaModelManager.ZIP_ACCESS_VERBOSE) {
638 .println("(" + Thread.currentThread() + ") [JavaModel.getTarget(...)] Checking existence of " + path.toString()); //$NON-NLS-1$ //$NON-NLS-2$
640 if (externalFile.exists()) {
641 // cache external file
642 existingExternalFiles.add(externalFile);