replace deprecated org.eclipse.jface.text.Assert with org.eclipse.core.runtime.Assert
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / core / JavaModel.java
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
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.core;
12
13 import java.io.File;
14 import java.util.ArrayList;
15 import java.util.HashSet;
16 import java.util.Map;
17
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;
26
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 //incastrix
38 //import org.eclipse.jface.text.Assert;
39 import org.eclipse.core.runtime.Assert;
40
41 /**
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.
46  *
47  * @see IJavaModel
48  */
49 public class JavaModel extends Openable implements IJavaModel {
50
51         /**
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.
54          */
55         public static HashSet existingExternalFiles = new HashSet();
56
57         /**
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.
61          * 
62          * @exception Error
63          *                if called more than once
64          */
65         protected JavaModel() throws Error {
66                 super(null, "" /* workspace has empty name */); //$NON-NLS-1$
67         }
68
69         protected boolean buildStructure(OpenableElementInfo info,
70                         IProgressMonitor pm, Map newElements, IResource underlyingResource) /*
71                                                                                                                                                                  * throws
72                                                                                                                                                                  * JavaModelException
73                                                                                                                                                                  */{
74
75                 // determine my children
76                 IProject[] projects = ResourcesPlugin.getWorkspace().getRoot()
77                                 .getProjects();
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));
82                         }
83                 }
84
85                 newElements.put(this, info);
86
87                 return true;
88         }
89
90         /*
91          * @see IJavaModel
92          */
93         public boolean contains(IResource resource) {
94                 switch (resource.getType()) {
95                 case IResource.ROOT:
96                 case IResource.PROJECT:
97                         return true;
98                 }
99                 // file or folder
100                 IJavaProject[] projects;
101                 try {
102                         projects = this.getJavaProjects();
103                 } catch (JavaModelException e) {
104                         return false;
105                 }
106                 for (int i = 0, length = projects.length; i < length; i++) {
107                         JavaProject project = (JavaProject) projects[i];
108
109                         if (!project.contains(resource)) {
110                                 return false;
111                         }
112                 }
113                 return true;
114         }
115
116         /**
117          * @see IJavaModel
118          */
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);
126                 } else {
127                         runOperation(
128                                         new CopyElementsOperation(elements, containers, force),
129                                         elements, siblings, renamings, monitor);
130                 }
131         }
132
133         /**
134          * Returns a new element info for this element.
135          */
136         protected Object createElementInfo() {
137                 return new JavaModelInfo();
138         }
139
140         /**
141          * @see IJavaModel
142          */
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),
148                                         monitor);
149                 } else {
150                         runOperation(new DeleteElementsOperation(elements, force), monitor);
151                 }
152         }
153
154         /**
155          * Finds the given project in the list of the java model's children. Returns
156          * null if not found.
157          */
158         public IJavaProject findJavaProject(IProject project) {
159                 try {
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())) {
164                                         return javaProject;
165                                 }
166                         }
167                 } catch (JavaModelException e) {
168                 }
169                 return null;
170         }
171
172         /**
173          * @see IJavaElement
174          */
175         public int getElementType() {
176                 return JAVA_MODEL;
177         }
178
179         /**
180          * Flushes the cache of external files known to be existing.
181          */
182         public static void flushExternalFileCache() {
183                 existingExternalFiles = new HashSet();
184         }
185
186         /**
187          */
188         protected boolean generateInfos(OpenableElementInfo info,
189                         IProgressMonitor pm, Map newElements, IResource underlyingResource)
190                         throws JavaModelException {
191
192                 JavaModelManager.getJavaModelManager().putInfo(this, info);
193                 // determine my children
194                 IProject[] projects = ResourcesPlugin.getWorkspace().getRoot()
195                                 .getProjects();
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));
200                         }
201                 }
202                 return true;
203         }
204
205         /**
206          * Returns the <code>IJavaElement</code> represented by the
207          * <code>String</code> memento.
208          * 
209          * @see getHandleMemento()
210          */
211         // protected IJavaElement getHandleFromMementoForBinaryMembers(String
212         // memento, IPackageFragmentRoot root, int rootEnd, int end) throws
213         // JavaModelException {
214         //
215         // //deal with class file and binary members
216         // IPackageFragment frag = null;
217         // if (rootEnd == end - 1) {
218         // //default package
219         // frag= root.getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME);
220         // } else {
221         // frag= root.getPackageFragment(memento.substring(rootEnd + 1, end));
222         // }
223         // int oldEnd = end;
224         // end = memento.indexOf(JavaElement.JEM_TYPE, oldEnd);
225         // if (end == -1) {
226         // //we ended with a class file
227         // return frag.getClassFile(memento.substring(oldEnd + 1));
228         // }
229         // IClassFile cf = frag.getClassFile(memento.substring(oldEnd + 1, end));
230         // oldEnd = end;
231         // end = memento.indexOf(JavaElement.JEM_TYPE, oldEnd);
232         // oldEnd = end;
233         // end = memento.indexOf(JavaElement.JEM_FIELD, end);
234         // if (end != -1) {
235         // //binary field
236         // IType type = cf.getType();
237         // return type.getField(memento.substring(end + 1));
238         // }
239         // end = memento.indexOf(JavaElement.JEM_METHOD, oldEnd);
240         // if (end != -1) {
241         // //binary method
242         // oldEnd = end;
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[] {};
251         // } else {
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();
257         // int i = 0;
258         // while (tokenizer.hasMoreTokens()) {
259         // parameterTypes[i] = tokenizer.nextToken();
260         // i++;
261         // }
262         // }
263         // return type.getMethod(methodName, parameterTypes);
264         // }
265         //
266         // //binary type
267         // return cf.getType();
268         // }
269         /**
270          * Returns the <code>IPackageFragmentRoot</code> represented by the
271          * <code>String</code> memento.
272          * 
273          * @see getHandleMemento()
274          */
275         // protected IPackageFragmentRoot getHandleFromMementoForRoot(String
276         // memento, JavaProject project, int projectEnd, int rootEnd) {
277         // String rootName = null;
278         // if (rootEnd == projectEnd - 1) {
279         // //default root
280         // rootName = IPackageFragmentRoot.DEFAULT_PACKAGEROOT_PATH;
281         // } else {
282         // rootName = memento.substring(projectEnd + 1, rootEnd);
283         // }
284         // return project.getPackageFragmentRoot(new Path(rootName));
285         // }
286         /**
287          * Returns the <code>IJavaElement</code> represented by the
288          * <code>String</code> memento.
289          * 
290          * @see getHandleMemento()
291          */
292         // protected IJavaElement getHandleFromMementoForSourceMembers(String
293         // memento, IPackageFragmentRoot root, int rootEnd, int end) throws
294         // JavaModelException {
295         //
296         // //deal with compilation units and source members
297         // IPackageFragment frag = null;
298         // if (rootEnd == end - 1) {
299         // //default package
300         // frag= root.getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME);
301         // } else {
302         // frag= root.getPackageFragment(memento.substring(rootEnd + 1, end));
303         // }
304         // int oldEnd = end;
305         // end = memento.indexOf(JavaElement.JEM_PACKAGEDECLARATION, end);
306         // if (end != -1) {
307         // //package declaration
308         // ICompilationUnit cu = frag.getCompilationUnit(memento.substring(oldEnd +
309         // 1, end));
310         // return cu.getPackageDeclaration(memento.substring(end + 1));
311         // }
312         // end = memento.indexOf(JavaElement.JEM_IMPORTDECLARATION, oldEnd);
313         // if (end != -1) {
314         // //import declaration
315         // ICompilationUnit cu = frag.getCompilationUnit(memento.substring(oldEnd +
316         // 1, end));
317         // return cu.getImport(memento.substring(end + 1));
318         // }
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));
323         // }
324         //
325         // //source members
326         // ICompilationUnit cu = frag.getCompilationUnit(memento.substring(oldEnd +
327         // 1, typeStart));
328         // end = memento.indexOf(JavaElement.JEM_FIELD, oldEnd);
329         // if (end != -1) {
330         // //source field
331         // IType type = getHandleFromMementoForSourceType(memento, cu, typeStart,
332         // end);
333         // return type.getField(memento.substring(end + 1));
334         // }
335         // end = memento.indexOf(JavaElement.JEM_METHOD, oldEnd);
336         // if (end != -1) {
337         // //source method
338         // IType type = getHandleFromMementoForSourceType(memento, cu, typeStart,
339         // end);
340         // oldEnd = end;
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[] {};
348         // } else {
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();
354         // int i = 0;
355         // while (mTokenizer.hasMoreTokens()) {
356         // parameterTypes[i] = mTokenizer.nextToken();
357         // i++;
358         // }
359         // }
360         // return type.getMethod(methodName, parameterTypes);
361         // }
362         //      
363         // end = memento.indexOf(JavaElement.JEM_INITIALIZER, oldEnd);
364         // if (end != -1 ) {
365         // //initializer
366         // IType type = getHandleFromMementoForSourceType(memento, cu, typeStart,
367         // end);
368         // return type.getInitializer(Integer.parseInt(memento.substring(end + 1)));
369         // }
370         // //source type
371         // return getHandleFromMementoForSourceType(memento, cu, typeStart,
372         // memento.length());
373         // }
374         /**
375          * Returns the <code>IJavaElement</code> represented by the
376          * <code>String</code> memento.
377          * 
378          * @see getHandleMemento()
379          */
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);
388         //              
389         // } else {
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());
397         // }
398         // }
399         // return type;
400         // }
401
402         /*
403          * @see JavaElement
404          */
405         public IJavaElement getHandleFromMemento(String token,
406                         MementoTokenizer memento, WorkingCopyOwner owner) {
407                 switch (token.charAt(0)) {
408                 case JEM_COUNT:
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);
414                 }
415                 return null;
416         }
417
418         /**
419          * @see JavaElement#getHandleMemento()
420          */
421         public String getHandleMemento() {
422                 return getElementName();
423         }
424
425         /**
426          * Returns the <code>char</code> that marks the start of this handles
427          * contribution to a memento.
428          */
429         protected char getHandleMementoDelimiter() {
430                 Assert.isTrue(false, "Should not be called"); //$NON-NLS-1$
431                 return 0;
432         }
433
434         /**
435          * @see IJavaModel
436          */
437         public IJavaProject getJavaProject(String name) {
438                 return new JavaProject(ResourcesPlugin.getWorkspace().getRoot()
439                                 .getProject(name), this);
440         }
441
442         /**
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.
445          * 
446          * @exception IllegalArgumentException
447          *                if the given resource is not one of an IProject, IFolder,
448          *                or IFile.
449          */
450         public IJavaProject getJavaProject(IResource resource) {
451                 switch (resource.getType()) {
452                 case IResource.FOLDER:
453                         return new JavaProject(((IFolder) resource).getProject(), this);
454                 case IResource.FILE:
455                         return new JavaProject(((IFile) resource).getProject(), this);
456                 case IResource.PROJECT:
457                         return new JavaProject((IProject) resource, this);
458                 default:
459                         throw new IllegalArgumentException(Util
460                                         .bind("element.invalidResourceForProject")); //$NON-NLS-1$
461                 }
462         }
463
464         /**
465          * @see IJavaModel
466          */
467         public IJavaProject[] getJavaProjects() throws JavaModelException {
468                 ArrayList list = getChildrenOfType(JAVA_PROJECT);
469                 IJavaProject[] array = new IJavaProject[list.size()];
470                 list.toArray(array);
471                 return array;
472
473         }
474
475         // /**
476         // * @see IJavaModel
477         // */
478         // public Object[] getNonJavaResources() throws JavaModelException {
479         // return ((JavaModelInfo) getElementInfo()).getNonJavaResources();
480         // }
481
482         /**
483          * Workaround for bug 15168 circular errors not reported Returns the list of
484          * java projects before resource delta processing has started.
485          */
486         public IJavaProject[] getOldJavaProjectsList() throws JavaModelException {
487                 JavaModelManager manager = JavaModelManager.getJavaModelManager();
488                 return manager.javaProjectsCache == null ? this.getJavaProjects()
489                                 : manager.javaProjectsCache;
490         }
491
492         /*
493          * @see IJavaElement
494          */
495         public IPath getPath() {
496                 return Path.ROOT;
497         }
498
499         /*
500          * @see IJavaElement
501          */
502         public IResource getResource() {
503                 return ResourcesPlugin.getWorkspace().getRoot();
504         }
505
506         /**
507          * @see IOpenable
508          */
509         public IResource getUnderlyingResource() throws JavaModelException {
510                 return null;
511         }
512
513         /**
514          * Returns the workbench associated with this object.
515          */
516         public IWorkspace getWorkspace() {
517                 return ResourcesPlugin.getWorkspace();
518         }
519
520         /**
521          * @see IJavaModel
522          */
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);
530                 } else {
531                         runOperation(
532                                         new MoveElementsOperation(elements, containers, force),
533                                         elements, siblings, renamings, monitor);
534                 }
535         }
536
537         /**
538          * @see IJavaModel#refreshExternalArchives(IJavaElement[], IProgressMonitor)
539          */
540         // public void refreshExternalArchives(IJavaElement[] elementsScope,
541         // IProgressMonitor monitor) throws JavaModelException {
542         // if (elementsScope == null){
543         // elementsScope = new IJavaElement[] { this };
544         // }
545         // JavaModelManager.getJavaModelManager().deltaProcessor.checkExternalArchiveChanges(elementsScope,
546         // monitor);
547         // }
548         /**
549          * @see IJavaModel
550          */
551         public void rename(IJavaElement[] elements, IJavaElement[] destinations,
552                         String[] renamings, boolean force, IProgressMonitor monitor)
553                         throws JavaModelException {
554                 MultiOperation op;
555                 if (elements != null && elements.length > 0 && elements[0] != null
556                                 && elements[0].getElementType() < IJavaElement.TYPE) {
557                         op = new RenameResourceElementsOperation(elements, destinations,
558                                         renamings, force);
559                 } else {
560                         op = new RenameElementsOperation(elements, destinations, renamings,
561                                         force);
562                 }
563
564                 runOperation(op, monitor);
565         }
566
567         /*
568          * @see JavaElement#rootedAt(IJavaProject)
569          */
570         public IJavaElement rootedAt(IJavaProject project) {
571                 return this;
572
573         }
574
575         /**
576          * Configures and runs the <code>MultiOperation</code>.
577          */
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]);
585                         }
586                 }
587                 // runOperation(op, monitor);
588                 op.runOperation(monitor);
589         }
590
591         /**
592          * @private Debugging purposes
593          */
594         protected void toStringInfo(int tab, StringBuffer buffer, Object info) {
595                 buffer.append(this.tabString(tab));
596                 buffer.append("Java Model"); //$NON-NLS-1$
597                 if (info == null) {
598                         buffer.append(" (not open)"); //$NON-NLS-1$
599                 }
600         }
601
602         /**
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.
606          */
607         public static Object getTarget(IContainer container, IPath path,
608                         boolean checkResourceExistence) {
609
610                 if (path == null)
611                         return null;
612
613                 // lookup - inside the container
614                 if (path.getDevice() == null) { // container relative paths should not
615                                                                                 // contain a device
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())
621                                         return resource;
622                                 return null;
623                         }
624                 }
625
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())
629                         return null;
630
631                 // lookup - outside the container
632                 File externalFile = new File(path.toOSString());
633                 if (!checkResourceExistence) {
634                         return externalFile;
635                 } else if (existingExternalFiles.contains(externalFile)) {
636                         return externalFile;
637                 } else {
638                         if (JavaModelManager.ZIP_ACCESS_VERBOSE) {
639                                 System.out
640                                                 .println("(" + Thread.currentThread() + ") [JavaModel.getTarget(...)] Checking existence of " + path.toString()); //$NON-NLS-1$ //$NON-NLS-2$
641                         }
642                         if (externalFile.exists()) {
643                                 // cache external file
644                                 existingExternalFiles.add(externalFile);
645                                 return externalFile;
646                         }
647                 }
648                 return null;
649         }
650 }