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;
23 import org.eclipse.core.resources.IContainer;
24 import org.eclipse.core.resources.IFile;
25 import org.eclipse.core.resources.IFolder;
26 import org.eclipse.core.resources.IProject;
27 import org.eclipse.core.resources.IResource;
28 import org.eclipse.core.resources.IWorkspace;
29 import org.eclipse.core.resources.ResourcesPlugin;
30 import org.eclipse.core.runtime.IPath;
31 import org.eclipse.core.runtime.IProgressMonitor;
32 import org.eclipse.core.runtime.Path;
33 import org.eclipse.jface.util.Assert;
37 * Implementation of <code>IJavaModel<code>. The Java Model maintains a cache of
38 * active <code>IJavaProject</code>s in a workspace. A Java Model is specific to a
39 * workspace. To retrieve a workspace's model, use the
40 * <code>#getJavaModel(IWorkspace)</code> method.
44 public class JavaModel extends Openable implements IJavaModel {
47 * A set of java.io.Files used as a cache of external jars that
48 * are known to be existing.
49 * Note this cache is kept for the whole session.
51 public static HashSet existingExternalFiles = new HashSet();
54 * Constructs a new Java Model on the given workspace.
55 * Note that only one instance of JavaModel handle should ever be created.
56 * One should only indirect through JavaModelManager#getJavaModel() to get
59 * @exception Error if called more than once
61 protected JavaModel() throws Error {
62 super(JAVA_MODEL, null, "" /*workspace has empty name*/); //$NON-NLS-1$
67 public boolean contains(IResource resource) {
68 switch (resource.getType()) {
70 case IResource.PROJECT:
74 IJavaProject[] projects;
76 projects = this.getJavaProjects();
77 } catch (JavaModelException e) {
80 for (int i = 0, length = projects.length; i < length; i++) {
81 JavaProject project = (JavaProject)projects[i];
83 if (!project.contains(resource)) {
92 public void copy(IJavaElement[] elements, IJavaElement[] containers, IJavaElement[] siblings, String[] renamings, boolean force, IProgressMonitor monitor) throws JavaModelException {
93 if (elements != null && elements.length > 0 && elements[0] != null && elements[0].getElementType() < IJavaElement.TYPE) {
94 runOperation(new CopyResourceElementsOperation(elements, containers, force), elements, siblings, renamings, monitor);
96 runOperation(new CopyElementsOperation(elements, containers, force), elements, siblings, renamings, monitor);
100 * Returns a new element info for this element.
102 protected OpenableElementInfo createElementInfo() {
103 return new JavaModelInfo();
109 public void delete(IJavaElement[] elements, boolean force, IProgressMonitor monitor) throws JavaModelException {
110 if (elements != null && elements.length > 0 && elements[0] != null && elements[0].getElementType() < IJavaElement.TYPE) {
111 runOperation(new DeleteResourceElementsOperation(elements, force), monitor);
113 runOperation(new DeleteElementsOperation(elements, force), monitor);
117 * Finds the given project in the list of the java model's children.
118 * Returns null if not found.
120 public IJavaProject findJavaProject(IProject project) {
122 IJavaProject[] projects = this.getOldJavaProjectsList();
123 for (int i = 0, length = projects.length; i < length; i++) {
124 IJavaProject javaProject = projects[i];
125 if (project.equals(javaProject.getProject())) {
129 } catch (JavaModelException e) {
135 * Flushes the cache of external files known to be existing.
137 public static void flushExternalFileCache() {
138 existingExternalFiles = new HashSet();
143 protected boolean generateInfos(
144 OpenableElementInfo info,
147 IResource underlyingResource) throws JavaModelException {
149 JavaModelManager.getJavaModelManager().putInfo(this, info);
150 // determine my children
151 IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
152 for (int i = 0, max = projects.length; i < max; i++) {
153 IProject project = projects[i];
154 if (JavaProject.hasJavaNature(project)) {
155 info.addChild(getJavaProject(project));
161 * Returns the <code>IJavaElement</code> represented by the <code>String</code>
163 * @see getHandleMemento()
165 //protected IJavaElement getHandleFromMementoForBinaryMembers(String memento, IPackageFragmentRoot root, int rootEnd, int end) throws JavaModelException {
167 // //deal with class file and binary members
168 // IPackageFragment frag = null;
169 // if (rootEnd == end - 1) {
171 // frag= root.getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME);
173 // frag= root.getPackageFragment(memento.substring(rootEnd + 1, end));
176 // end = memento.indexOf(JavaElement.JEM_TYPE, oldEnd);
178 // //we ended with a class file
179 // return frag.getClassFile(memento.substring(oldEnd + 1));
181 // IClassFile cf = frag.getClassFile(memento.substring(oldEnd + 1, end));
183 // end = memento.indexOf(JavaElement.JEM_TYPE, oldEnd);
185 // end = memento.indexOf(JavaElement.JEM_FIELD, end);
188 // IType type = cf.getType();
189 // return type.getField(memento.substring(end + 1));
191 // end = memento.indexOf(JavaElement.JEM_METHOD, oldEnd);
195 // IType type = cf.getType();
196 // String methodName;
197 // end = memento.lastIndexOf(JavaElement.JEM_METHOD);
198 // String[] parameterTypes = null;
199 // if (end == oldEnd) {
200 // methodName = memento.substring(end + 1);
201 // //no parameter types
202 // parameterTypes = new String[] {};
204 // String parameters = memento.substring(oldEnd + 1);
205 // StringTokenizer tokenizer = new StringTokenizer(parameters, new String(new char[] {JavaElement.JEM_METHOD}));
206 // parameterTypes = new String[tokenizer.countTokens() - 1];
207 // methodName= tokenizer.nextToken();
209 // while (tokenizer.hasMoreTokens()) {
210 // parameterTypes[i] = tokenizer.nextToken();
214 // return type.getMethod(methodName, parameterTypes);
218 // return cf.getType();
221 * Returns the <code>IPackageFragmentRoot</code> represented by the <code>String</code>
223 * @see getHandleMemento()
225 //protected IPackageFragmentRoot getHandleFromMementoForRoot(String memento, JavaProject project, int projectEnd, int rootEnd) {
226 // String rootName = null;
227 // if (rootEnd == projectEnd - 1) {
229 // rootName = IPackageFragmentRoot.DEFAULT_PACKAGEROOT_PATH;
231 // rootName = memento.substring(projectEnd + 1, rootEnd);
233 // return project.getPackageFragmentRoot(new Path(rootName));
236 * Returns the <code>IJavaElement</code> represented by the <code>String</code>
238 * @see getHandleMemento()
240 //protected IJavaElement getHandleFromMementoForSourceMembers(String memento, IPackageFragmentRoot root, int rootEnd, int end) throws JavaModelException {
242 // //deal with compilation units and source members
243 // IPackageFragment frag = null;
244 // if (rootEnd == end - 1) {
246 // frag= root.getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME);
248 // frag= root.getPackageFragment(memento.substring(rootEnd + 1, end));
251 // end = memento.indexOf(JavaElement.JEM_PACKAGEDECLARATION, end);
253 // //package declaration
254 // ICompilationUnit cu = frag.getCompilationUnit(memento.substring(oldEnd + 1, end));
255 // return cu.getPackageDeclaration(memento.substring(end + 1));
257 // end = memento.indexOf(JavaElement.JEM_IMPORTDECLARATION, oldEnd);
259 // //import declaration
260 // ICompilationUnit cu = frag.getCompilationUnit(memento.substring(oldEnd + 1, end));
261 // return cu.getImport(memento.substring(end + 1));
263 // int typeStart = memento.indexOf(JavaElement.JEM_TYPE, oldEnd);
264 // if (typeStart == -1) {
265 // //we ended with a compilation unit
266 // return frag.getCompilationUnit(memento.substring(oldEnd + 1));
270 // ICompilationUnit cu = frag.getCompilationUnit(memento.substring(oldEnd + 1, typeStart));
271 // end = memento.indexOf(JavaElement.JEM_FIELD, oldEnd);
274 // IType type = getHandleFromMementoForSourceType(memento, cu, typeStart, end);
275 // return type.getField(memento.substring(end + 1));
277 // end = memento.indexOf(JavaElement.JEM_METHOD, oldEnd);
280 // IType type = getHandleFromMementoForSourceType(memento, cu, typeStart, end);
282 // String methodName;
283 // end = memento.lastIndexOf(JavaElement.JEM_METHOD);
284 // String[] parameterTypes = null;
285 // if (end == oldEnd) {
286 // methodName = memento.substring(end + 1);
287 // //no parameter types
288 // parameterTypes = new String[] {};
290 // String parameters = memento.substring(oldEnd + 1);
291 // StringTokenizer mTokenizer = new StringTokenizer(parameters, new String(new char[] {JavaElement.JEM_METHOD}));
292 // parameterTypes = new String[mTokenizer.countTokens() - 1];
293 // methodName = mTokenizer.nextToken();
295 // while (mTokenizer.hasMoreTokens()) {
296 // parameterTypes[i] = mTokenizer.nextToken();
300 // return type.getMethod(methodName, parameterTypes);
303 // end = memento.indexOf(JavaElement.JEM_INITIALIZER, oldEnd);
306 // IType type = getHandleFromMementoForSourceType(memento, cu, typeStart, end);
307 // return type.getInitializer(Integer.parseInt(memento.substring(end + 1)));
310 // return getHandleFromMementoForSourceType(memento, cu, typeStart, memento.length());
313 * Returns the <code>IJavaElement</code> represented by the <code>String</code>
315 * @see getHandleMemento()
317 //protected IType getHandleFromMementoForSourceType(String memento, ICompilationUnit cu, int typeStart, int typeEnd) throws JavaModelException {
318 // int end = memento.lastIndexOf(JavaElement.JEM_TYPE);
319 // IType type = null;
320 // if (end == typeStart) {
321 // String typeName = memento.substring(typeStart + 1, typeEnd);
322 // type = cu.getType(typeName);
325 // String typeNames = memento.substring(typeStart + 1, typeEnd);
326 // StringTokenizer tokenizer = new StringTokenizer(typeNames, new String(new char[] {JavaElement.JEM_TYPE}));
327 // type = cu.getType(tokenizer.nextToken());
328 // while (tokenizer.hasMoreTokens()) {
329 // //deal with inner types
330 // type= type.getType(tokenizer.nextToken());
336 * @see JavaElement#getHandleMemento()
338 public String getHandleMemento(){
339 return getElementName();
342 * Returns the <code>char</code> that marks the start of this handles
343 * contribution to a memento.
345 protected char getHandleMementoDelimiter(){
346 Assert.isTrue(false, "Should not be called"); //$NON-NLS-1$
352 public IJavaProject getJavaProject(String name) {
353 return new JavaProject(ResourcesPlugin.getWorkspace().getRoot().getProject(name), this);
356 * Returns the active Java project associated with the specified
357 * resource, or <code>null</code> if no Java project yet exists
360 * @exception IllegalArgumentException if the given resource
361 * is not one of an IProject, IFolder, or IFile.
363 public IJavaProject getJavaProject(IResource resource) {
364 switch(resource.getType()){
365 case IResource.FOLDER:
366 return new JavaProject(((IFolder)resource).getProject(), this);
368 return new JavaProject(((IFile)resource).getProject(), this);
369 case IResource.PROJECT:
370 return new JavaProject((IProject)resource, this);
372 throw new IllegalArgumentException(Util.bind("element.invalidResourceForProject")); //$NON-NLS-1$
378 public IJavaProject[] getJavaProjects() throws JavaModelException {
379 ArrayList list = getChildrenOfType(JAVA_PROJECT);
380 IJavaProject[] array= new IJavaProject[list.size()];
388 //public Object[] getNonJavaResources() throws JavaModelException {
389 // return ((JavaModelInfo) getElementInfo()).getNonJavaResources();
393 * Workaround for bug 15168 circular errors not reported
394 * Returns the list of java projects before resource delta processing
397 public IJavaProject[] getOldJavaProjectsList() throws JavaModelException {
398 JavaModelManager manager = JavaModelManager.getJavaModelManager();
400 manager.javaProjectsCache == null ?
401 this.getJavaProjects() :
402 manager.javaProjectsCache;
407 public IPath getPath() {
413 public IResource getResource() {
414 return ResourcesPlugin.getWorkspace().getRoot();
419 public IResource getUnderlyingResource() throws JavaModelException {
423 * Returns the workbench associated with this object.
425 public IWorkspace getWorkspace() {
426 return ResourcesPlugin.getWorkspace();
432 public void move(IJavaElement[] elements, IJavaElement[] containers, IJavaElement[] siblings, String[] renamings, boolean force, IProgressMonitor monitor) throws JavaModelException {
433 if (elements != null && elements.length > 0 && elements[0] != null && elements[0].getElementType() < IJavaElement.TYPE) {
434 runOperation(new MoveResourceElementsOperation(elements, containers, force), elements, siblings, renamings, monitor);
436 runOperation(new MoveElementsOperation(elements, containers, force), elements, siblings, renamings, monitor);
441 * @see IJavaModel#refreshExternalArchives(IJavaElement[], IProgressMonitor)
443 //public void refreshExternalArchives(IJavaElement[] elementsScope, IProgressMonitor monitor) throws JavaModelException {
444 // if (elementsScope == null){
445 // elementsScope = new IJavaElement[] { this };
447 // JavaModelManager.getJavaModelManager().deltaProcessor.checkExternalArchiveChanges(elementsScope, monitor);
453 public void rename(IJavaElement[] elements, IJavaElement[] destinations, String[] renamings, boolean force, IProgressMonitor monitor) throws JavaModelException {
455 if (elements != null && elements.length > 0 && elements[0] != null && elements[0].getElementType() < IJavaElement.TYPE) {
456 op = new RenameResourceElementsOperation(elements, destinations, renamings, force);
458 op = new RenameElementsOperation(elements, destinations, renamings, force);
461 runOperation(op, monitor);
464 * @see JavaElement#rootedAt(IJavaProject)
466 public IJavaElement rootedAt(IJavaProject project) {
471 * Configures and runs the <code>MultiOperation</code>.
473 protected void runOperation(MultiOperation op, IJavaElement[] elements, IJavaElement[] siblings, String[] renamings, IProgressMonitor monitor) throws JavaModelException {
474 op.setRenamings(renamings);
475 if (siblings != null) {
476 for (int i = 0; i < elements.length; i++) {
477 op.setInsertBefore(elements[i], siblings[i]);
480 runOperation(op, monitor);
483 * @private Debugging purposes
485 protected void toStringInfo(int tab, StringBuffer buffer, Object info) {
486 buffer.append(this.tabString(tab));
487 buffer.append("Java Model"); //$NON-NLS-1$
489 buffer.append(" (not open)"); //$NON-NLS-1$
494 * Helper method - returns the targeted item (IResource if internal or java.io.File if external),
496 * Internal items must be referred to using container relative paths.
498 public static Object getTarget(IContainer container, IPath path, boolean checkResourceExistence) {
500 if (path == null) return null;
502 // lookup - inside the container
503 if (path.getDevice() == null) { // container relative paths should not contain a device
504 // (see http://dev.eclipse.org/bugs/show_bug.cgi?id=18684)
505 // (case of a workspace rooted at d:\ )
506 IResource resource = container.findMember(path);
507 if (resource != null){
508 if (!checkResourceExistence ||resource.exists()) return resource;
513 // if path is relative, it cannot be an external path
514 // (see http://dev.eclipse.org/bugs/show_bug.cgi?id=22517)
515 if (!path.isAbsolute()) return null;
517 // lookup - outside the container
518 File externalFile = new File(path.toOSString());
519 if (!checkResourceExistence) {
521 } else if (existingExternalFiles.contains(externalFile)) {
524 if (JavaModelManager.ZIP_ACCESS_VERBOSE) {
525 System.out.println("(" + Thread.currentThread() + ") [JavaModel.getTarget(...)] Checking existence of " + path.toString()); //$NON-NLS-1$ //$NON-NLS-2$
527 if (externalFile.exists()) {
528 // cache external file
529 existingExternalFiles.add(externalFile);