d24e00b13f4e455a36cf88eba4d999c60d7ff3ad
[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.JavaModelException;
22 import net.sourceforge.phpdt.internal.core.util.Util;
23
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;
38
39
40 /**
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.
45  *
46  * @see IJavaModel
47  */
48 public class JavaModel extends Openable implements IJavaModel {
49
50         /**
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.
54          */ 
55         public static HashSet existingExternalFiles = new HashSet();
56                 
57 /**
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
61  * access to it.
62  * 
63  * @exception Error if called more than once
64  */
65 protected JavaModel() throws Error {
66         super(null, "" /*workspace has empty name*/); //$NON-NLS-1$
67 }
68 protected boolean buildStructure(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource)  /*throws JavaModelException*/ {
69
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));
76                 }
77         }
78
79         newElements.put(this, info);
80         
81         return true;
82 }
83 /*
84  * @see IJavaModel
85  */
86 public boolean contains(IResource resource) {
87         switch (resource.getType()) {
88                 case IResource.ROOT:
89                 case IResource.PROJECT:
90                         return true;
91         }
92         // file or folder
93         IJavaProject[] projects;
94         try {
95                 projects = this.getJavaProjects();
96         } catch (JavaModelException e) {
97                 return false;
98         }
99         for (int i = 0, length = projects.length; i < length; i++) {
100                 JavaProject project = (JavaProject)projects[i];
101         
102                 if (!project.contains(resource)) {
103                         return false;
104                 }
105         }
106         return true;
107 }
108 /**
109  * @see IJavaModel
110  */
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);
114         } else {
115                 runOperation(new CopyElementsOperation(elements, containers, force), elements, siblings, renamings, monitor);
116         }
117 }
118 /**
119  * Returns a new element info for this element.
120  */
121 protected Object createElementInfo() {
122         return new JavaModelInfo();
123 }
124
125 /**
126  * @see IJavaModel
127  */
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);
131         } else {
132                 runOperation(new DeleteElementsOperation(elements, force), monitor);
133         }
134 }
135 /**
136  * Finds the given project in the list of the java model's children.
137  * Returns null if not found.
138  */
139 public IJavaProject findJavaProject(IProject project) {
140         try {
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())) {
145                                 return javaProject;
146                         }
147                 }
148         } catch (JavaModelException e) {
149         }
150         return null;
151 }
152 /**
153  * @see IJavaElement
154  */
155 public int getElementType() {
156         return JAVA_MODEL;
157 }
158 /**
159  * Flushes the cache of external files known to be existing.
160  */
161 public static void flushExternalFileCache() {
162         existingExternalFiles = new HashSet();
163 }
164
165 /**
166  */
167 protected boolean generateInfos(
168         OpenableElementInfo info,
169         IProgressMonitor pm,
170         Map newElements,
171         IResource underlyingResource)   throws JavaModelException {
172
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));
180                 }
181         }
182         return true;
183 }
184 /**
185  * Returns the <code>IJavaElement</code> represented by the <code>String</code>
186  * memento.
187  * @see getHandleMemento()
188  */
189 //protected IJavaElement getHandleFromMementoForBinaryMembers(String memento, IPackageFragmentRoot root, int rootEnd, int end) throws JavaModelException {
190 //
191 //      //deal with class file and binary members
192 //      IPackageFragment frag = null;
193 //      if (rootEnd == end - 1) {
194 //              //default package
195 //              frag= root.getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME);
196 //      } else {
197 //              frag= root.getPackageFragment(memento.substring(rootEnd + 1, end));
198 //      }
199 //      int oldEnd = end;
200 //      end = memento.indexOf(JavaElement.JEM_TYPE, oldEnd);
201 //      if (end == -1) {
202 //              //we ended with a class file 
203 //              return frag.getClassFile(memento.substring(oldEnd + 1));
204 //      }
205 //      IClassFile cf = frag.getClassFile(memento.substring(oldEnd + 1, end));
206 //      oldEnd = end;
207 //      end = memento.indexOf(JavaElement.JEM_TYPE, oldEnd);
208 //      oldEnd = end;
209 //      end = memento.indexOf(JavaElement.JEM_FIELD, end);
210 //      if (end != -1) {
211 //              //binary field
212 //              IType type = cf.getType();
213 //              return type.getField(memento.substring(end + 1));
214 //      }
215 //      end = memento.indexOf(JavaElement.JEM_METHOD, oldEnd);
216 //      if (end != -1) {
217 //              //binary method
218 //              oldEnd = end;
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[] {};
227 //              } else {
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();
232 //                      int i = 0;
233 //                      while (tokenizer.hasMoreTokens()) {
234 //                              parameterTypes[i] = tokenizer.nextToken();
235 //                              i++;
236 //                      }
237 //              }
238 //              return type.getMethod(methodName, parameterTypes);
239 //      }
240 //
241 //      //binary type
242 //      return cf.getType();
243 //}
244 /**
245  * Returns the <code>IPackageFragmentRoot</code> represented by the <code>String</code>
246  * memento.
247  * @see getHandleMemento()
248  */
249 //protected IPackageFragmentRoot getHandleFromMementoForRoot(String memento, JavaProject project, int projectEnd, int rootEnd) {
250 //      String rootName = null;
251 //      if (rootEnd == projectEnd - 1) {
252 //              //default root
253 //              rootName = IPackageFragmentRoot.DEFAULT_PACKAGEROOT_PATH;
254 //      } else {
255 //              rootName = memento.substring(projectEnd + 1, rootEnd);
256 //      }
257 //      return project.getPackageFragmentRoot(new Path(rootName));
258 //}
259 /**
260  * Returns the <code>IJavaElement</code> represented by the <code>String</code>
261  * memento.
262  * @see getHandleMemento()
263  */
264 //protected IJavaElement getHandleFromMementoForSourceMembers(String memento, IPackageFragmentRoot root, int rootEnd, int end) throws JavaModelException {
265 //
266 //      //deal with compilation units and source members
267 //      IPackageFragment frag = null;
268 //      if (rootEnd == end - 1) {
269 //              //default package
270 //              frag= root.getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME);
271 //      } else {
272 //              frag= root.getPackageFragment(memento.substring(rootEnd + 1, end));
273 //      }
274 //      int oldEnd = end;
275 //      end = memento.indexOf(JavaElement.JEM_PACKAGEDECLARATION, end);
276 //      if (end != -1) {
277 //              //package declaration
278 //              ICompilationUnit cu = frag.getCompilationUnit(memento.substring(oldEnd + 1, end));
279 //              return cu.getPackageDeclaration(memento.substring(end + 1));
280 //      }
281 //      end = memento.indexOf(JavaElement.JEM_IMPORTDECLARATION, oldEnd);
282 //      if (end != -1) {
283 //              //import declaration
284 //              ICompilationUnit cu = frag.getCompilationUnit(memento.substring(oldEnd + 1, end));
285 //              return cu.getImport(memento.substring(end + 1));
286 //      }
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));
291 //      }
292 //
293 //      //source members
294 //      ICompilationUnit cu = frag.getCompilationUnit(memento.substring(oldEnd + 1, typeStart));
295 //      end = memento.indexOf(JavaElement.JEM_FIELD, oldEnd);
296 //      if (end != -1) {
297 //              //source field
298 //              IType type = getHandleFromMementoForSourceType(memento, cu, typeStart, end);
299 //              return type.getField(memento.substring(end + 1));
300 //      }
301 //      end = memento.indexOf(JavaElement.JEM_METHOD, oldEnd);
302 //      if (end != -1) {
303 //              //source method
304 //              IType type = getHandleFromMementoForSourceType(memento, cu, typeStart, end);
305 //              oldEnd = 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[] {};
313 //              } else {
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();
318 //                      int i = 0;
319 //                      while (mTokenizer.hasMoreTokens()) {
320 //                              parameterTypes[i] = mTokenizer.nextToken();
321 //                              i++;
322 //                      }
323 //              }
324 //              return type.getMethod(methodName, parameterTypes);
325 //      }
326 //      
327 //      end = memento.indexOf(JavaElement.JEM_INITIALIZER, oldEnd);
328 //      if (end != -1 ) {
329 //              //initializer
330 //              IType type = getHandleFromMementoForSourceType(memento, cu, typeStart, end);
331 //              return type.getInitializer(Integer.parseInt(memento.substring(end + 1)));
332 //      }
333 //      //source type
334 //      return getHandleFromMementoForSourceType(memento, cu, typeStart, memento.length());
335 //}
336 /**
337  * Returns the <code>IJavaElement</code> represented by the <code>String</code>
338  * memento.
339  * @see getHandleMemento()
340  */
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);
347 //              
348 //      } else {
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());
355 //              }
356 //      }
357 //      return type;
358 //}
359
360
361 /**
362  * @see JavaElement#getHandleMemento()
363  */
364 public String getHandleMemento(){
365         return getElementName();
366 }
367 /**
368  * Returns the <code>char</code> that marks the start of this handles
369  * contribution to a memento.
370  */
371 protected char getHandleMementoDelimiter(){
372         Assert.isTrue(false, "Should not be called"); //$NON-NLS-1$
373         return 0;
374 }
375 /**
376  * @see IJavaModel
377  */
378 public IJavaProject getJavaProject(String name) {
379         return new JavaProject(ResourcesPlugin.getWorkspace().getRoot().getProject(name), this);
380 }
381 /**
382  * Returns the active Java project associated with the specified
383  * resource, or <code>null</code> if no Java project yet exists
384  * for the resource.
385  *
386  * @exception IllegalArgumentException if the given resource
387  * is not one of an IProject, IFolder, or IFile.
388  */
389 public IJavaProject getJavaProject(IResource resource) {
390         switch(resource.getType()){
391                 case IResource.FOLDER:
392                         return new JavaProject(((IFolder)resource).getProject(), this);
393                 case IResource.FILE:
394                         return new JavaProject(((IFile)resource).getProject(), this);
395                 case IResource.PROJECT:
396                         return new JavaProject((IProject)resource, this);
397                 default:
398                         throw new IllegalArgumentException(Util.bind("element.invalidResourceForProject")); //$NON-NLS-1$
399         }
400 }
401 /**
402  * @see IJavaModel
403  */
404 public IJavaProject[] getJavaProjects() throws JavaModelException {
405         ArrayList list = getChildrenOfType(JAVA_PROJECT);
406         IJavaProject[] array= new IJavaProject[list.size()];
407         list.toArray(array);
408         return array;
409
410 }
411 ///**
412 // * @see IJavaModel
413 // */
414 //public Object[] getNonJavaResources() throws JavaModelException {
415 //              return ((JavaModelInfo) getElementInfo()).getNonJavaResources();
416 //}
417
418 /**
419  * Workaround for bug 15168 circular errors not reported 
420  * Returns the list of java projects before resource delta processing
421  * has started.
422  */
423 public IJavaProject[] getOldJavaProjectsList() throws JavaModelException {
424         JavaModelManager manager = JavaModelManager.getJavaModelManager();
425         return 
426                 manager.javaProjectsCache == null ? 
427                         this.getJavaProjects() : 
428                         manager.javaProjectsCache; 
429 }
430 /*
431  * @see IJavaElement
432  */
433 public IPath getPath() {
434         return Path.ROOT;
435 }
436 /*
437  * @see IJavaElement
438  */
439 public IResource getResource() {
440         return ResourcesPlugin.getWorkspace().getRoot();
441 }
442 /**
443  * @see IOpenable
444  */
445 public IResource getUnderlyingResource() throws JavaModelException {
446         return null;
447 }
448 /**
449  * Returns the workbench associated with this object.
450  */
451 public IWorkspace getWorkspace() {
452         return ResourcesPlugin.getWorkspace();
453 }
454
455 /**
456  * @see IJavaModel
457  */
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);
461         } else {
462                 runOperation(new MoveElementsOperation(elements, containers, force), elements, siblings, renamings, monitor);
463         }
464 }
465
466 /**
467  * @see IJavaModel#refreshExternalArchives(IJavaElement[], IProgressMonitor)
468  */
469 //public void refreshExternalArchives(IJavaElement[] elementsScope, IProgressMonitor monitor) throws JavaModelException {
470 //      if (elementsScope == null){
471 //              elementsScope = new IJavaElement[] { this };
472 //      }
473 //      JavaModelManager.getJavaModelManager().deltaProcessor.checkExternalArchiveChanges(elementsScope, monitor);
474 //}
475
476 /**
477  * @see IJavaModel
478  */
479 public void rename(IJavaElement[] elements, IJavaElement[] destinations, String[] renamings, boolean force, IProgressMonitor monitor) throws JavaModelException {
480         MultiOperation op;
481         if (elements != null && elements.length > 0 && elements[0] != null && elements[0].getElementType() < IJavaElement.TYPE) {
482                 op = new RenameResourceElementsOperation(elements, destinations, renamings, force);
483         } else {
484                 op = new RenameElementsOperation(elements, destinations, renamings, force);
485         }
486         
487         runOperation(op, monitor);
488 }
489 /*
490  * @see JavaElement#rootedAt(IJavaProject)
491  */
492 public IJavaElement rootedAt(IJavaProject project) {
493         return this;
494
495 }
496 /**
497  * Configures and runs the <code>MultiOperation</code>.
498  */
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]);
504                 }
505         }
506         runOperation(op, monitor);
507 }
508 /**
509  * @private Debugging purposes
510  */
511 protected void toStringInfo(int tab, StringBuffer buffer, Object info) {
512         buffer.append(this.tabString(tab));
513         buffer.append("Java Model"); //$NON-NLS-1$
514         if (info == null) {
515                 buffer.append(" (not open)"); //$NON-NLS-1$
516         }
517 }
518
519 /**
520  * Helper method - returns the targeted item (IResource if internal or java.io.File if external), 
521  * or null if unbound
522  * Internal items must be referred to using container relative paths.
523  */
524 public static Object getTarget(IContainer container, IPath path, boolean checkResourceExistence) {
525
526         if (path == null) return null;
527         
528         // lookup - inside the container
529         if (path.getDevice() == null) { // container relative paths should not contain a device 
530                                                                                                 // (see http://dev.eclipse.org/bugs/show_bug.cgi?id=18684)
531                                                                                                 // (case of a workspace rooted at d:\ )
532                 IResource resource = container.findMember(path);
533                 if (resource != null){
534                         if (!checkResourceExistence ||resource.exists()) return resource;
535                         return null;
536                 }
537         }
538         
539         // if path is relative, it cannot be an external path
540         // (see http://dev.eclipse.org/bugs/show_bug.cgi?id=22517)
541         if (!path.isAbsolute()) return null; 
542
543         // lookup - outside the container
544         File externalFile = new File(path.toOSString());
545         if (!checkResourceExistence) {
546                 return externalFile;
547         } else if (existingExternalFiles.contains(externalFile)) {
548                 return externalFile;
549         } else { 
550                 if (JavaModelManager.ZIP_ACCESS_VERBOSE) {
551                         System.out.println("(" + Thread.currentThread() + ") [JavaModel.getTarget(...)] Checking existence of " + path.toString()); //$NON-NLS-1$ //$NON-NLS-2$
552                 }
553                 if (externalFile.exists()) {
554                         // cache external file
555                         existingExternalFiles.add(externalFile);
556                         return externalFile;
557                 }
558         }
559         return null;    
560 }
561 }