KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > core > JavaElement


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.core;
12
13 import java.io.BufferedInputStream JavaDoc;
14 import java.io.FileNotFoundException JavaDoc;
15 import java.io.IOException JavaDoc;
16 import java.io.InputStream JavaDoc;
17 import java.io.PrintWriter JavaDoc;
18 import java.io.StringWriter JavaDoc;
19 import java.net.JarURLConnection JavaDoc;
20 import java.net.MalformedURLException JavaDoc;
21 import java.net.URL JavaDoc;
22 import java.net.URLConnection JavaDoc;
23 import java.util.ArrayList JavaDoc;
24 import java.util.HashMap JavaDoc;
25
26 import org.eclipse.core.resources.IResource;
27 import org.eclipse.core.runtime.*;
28 import org.eclipse.core.runtime.jobs.ISchedulingRule;
29 import org.eclipse.jdt.core.*;
30 import org.eclipse.jdt.core.dom.ASTNode;
31 import org.eclipse.jdt.core.dom.CompilationUnit;
32 import org.eclipse.jdt.internal.compiler.lookup.Binding;
33 import org.eclipse.jdt.internal.core.util.MementoTokenizer;
34 import org.eclipse.jdt.internal.core.util.Util;
35
36 /**
37  * Root of Java element handle hierarchy.
38  *
39  * @see IJavaElement
40  */

41 public abstract class JavaElement extends PlatformObject implements IJavaElement {
42 // private static final QualifiedName PROJECT_JAVADOC= new QualifiedName(JavaCore.PLUGIN_ID, "project_javadoc_location"); //$NON-NLS-1$
43

44     private static final byte[] CLOSING_DOUBLE_QUOTE = new byte[] { 34 };
45     private static final byte[] CHARSET = new byte[] {99, 104, 97, 114, 115, 101, 116, 61 };
46     private static final byte[] CONTENT_TYPE = new byte[] { 34, 67, 111, 110, 116, 101, 110, 116, 45, 84, 121, 112, 101, 34 };
47     private static final byte[] CONTENT = new byte[] { 99, 111, 110, 116, 101, 110, 116, 61, 34 };
48     public static final char JEM_ESCAPE = '\\';
49     public static final char JEM_JAVAPROJECT = '=';
50     public static final char JEM_PACKAGEFRAGMENTROOT = '/';
51     public static final char JEM_PACKAGEFRAGMENT = '<';
52     public static final char JEM_FIELD = '^';
53     public static final char JEM_METHOD = '~';
54     public static final char JEM_INITIALIZER = '|';
55     public static final char JEM_COMPILATIONUNIT = '{';
56     public static final char JEM_CLASSFILE = '(';
57     public static final char JEM_TYPE = '[';
58     public static final char JEM_PACKAGEDECLARATION = '%';
59     public static final char JEM_IMPORTDECLARATION = '#';
60     public static final char JEM_COUNT = '!';
61     public static final char JEM_LOCALVARIABLE = '@';
62     public static final char JEM_TYPE_PARAMETER = ']';
63
64     /**
65      * This element's parent, or <code>null</code> if this
66      * element does not have a parent.
67      */

68     protected JavaElement parent;
69
70     protected static final JavaElement[] NO_ELEMENTS = new JavaElement[0];
71     protected static final Object JavaDoc NO_INFO = new Object JavaDoc();
72     
73     /**
74      * Constructs a handle for a java element with
75      * the given parent element.
76      *
77      * @param parent The parent of java element
78      *
79      * @exception IllegalArgumentException if the type is not one of the valid
80      * Java element type constants
81      *
82      */

83     protected JavaElement(JavaElement parent) throws IllegalArgumentException JavaDoc {
84         this.parent = parent;
85     }
86     /**
87      * @see IOpenable
88      */

89     public void close() throws JavaModelException {
90         JavaModelManager.getJavaModelManager().removeInfoAndChildren(this);
91     }
92     /**
93      * This element is being closed. Do any necessary cleanup.
94      */

95     protected abstract void closing(Object JavaDoc info) throws JavaModelException;
96     /*
97      * Returns a new element info for this element.
98      */

99     protected abstract Object JavaDoc createElementInfo();
100     /**
101      * Returns true if this handle represents the same Java element
102      * as the given handle. By default, two handles represent the same
103      * element if they are identical or if they represent the same type
104      * of element, have equal names, parents, and occurrence counts.
105      *
106      * <p>If a subclass has other requirements for equality, this method
107      * must be overridden.
108      *
109      * @see Object#equals
110      */

111     public boolean equals(Object JavaDoc o) {
112         
113         if (this == o) return true;
114     
115         // Java model parent is null
116
if (this.parent == null) return super.equals(o);
117     
118         // assume instanceof check is done in subclass
119
JavaElement other = (JavaElement) o;
120         return getElementName().equals(other.getElementName()) &&
121                 this.parent.equals(other.parent);
122     }
123     protected void escapeMementoName(StringBuffer JavaDoc buffer, String JavaDoc mementoName) {
124         for (int i = 0, length = mementoName.length(); i < length; i++) {
125             char character = mementoName.charAt(i);
126             switch (character) {
127                 case JEM_ESCAPE:
128                 case JEM_COUNT:
129                 case JEM_JAVAPROJECT:
130                 case JEM_PACKAGEFRAGMENTROOT:
131                 case JEM_PACKAGEFRAGMENT:
132                 case JEM_FIELD:
133                 case JEM_METHOD:
134                 case JEM_INITIALIZER:
135                 case JEM_COMPILATIONUNIT:
136                 case JEM_CLASSFILE:
137                 case JEM_TYPE:
138                 case JEM_PACKAGEDECLARATION:
139                 case JEM_IMPORTDECLARATION:
140                 case JEM_LOCALVARIABLE:
141                 case JEM_TYPE_PARAMETER:
142                     buffer.append(JEM_ESCAPE);
143             }
144             buffer.append(character);
145         }
146     }
147     /**
148      * @see IJavaElement
149      */

150     public boolean exists() {
151         
152         try {
153             getElementInfo();
154             return true;
155         } catch (JavaModelException e) {
156             // element doesn't exist: return false
157
}
158         return false;
159     }
160     
161     /**
162      * Returns the <code>ASTNode</code> that corresponds to this <code>JavaElement</code>
163      * or <code>null</code> if there is no corresponding node.
164      */

165     public ASTNode findNode(CompilationUnit ast) {
166         return null; // works only inside a compilation unit
167
}
168     /**
169      * Generates the element infos for this element, its ancestors (if they are not opened) and its children (if it is an Openable).
170      * Puts the newly created element info in the given map.
171      */

172     protected abstract void generateInfos(Object JavaDoc info, HashMap JavaDoc newElements, IProgressMonitor pm) throws JavaModelException;
173     
174     /**
175      * @see IJavaElement
176      */

177     public IJavaElement getAncestor(int ancestorType) {
178         
179         IJavaElement element = this;
180         while (element != null) {
181             if (element.getElementType() == ancestorType) return element;
182             element= element.getParent();
183         }
184         return null;
185     }
186     /**
187      * @see IParent
188      */

189     public IJavaElement[] getChildren() throws JavaModelException {
190         Object JavaDoc elementInfo = getElementInfo();
191         if (elementInfo instanceof JavaElementInfo) {
192             return ((JavaElementInfo)elementInfo).getChildren();
193         } else {
194             return NO_ELEMENTS;
195         }
196     }
197     /**
198      * Returns a collection of (immediate) children of this node of the
199      * specified type.
200      *
201      * @param type - one of the JEM_* constants defined by JavaElement
202      */

203     public ArrayList JavaDoc getChildrenOfType(int type) throws JavaModelException {
204         IJavaElement[] children = getChildren();
205         int size = children.length;
206         ArrayList JavaDoc list = new ArrayList JavaDoc(size);
207         for (int i = 0; i < size; ++i) {
208             JavaElement elt = (JavaElement)children[i];
209             if (elt.getElementType() == type) {
210                 list.add(elt);
211             }
212         }
213         return list;
214     }
215     /**
216      * @see IMember
217      */

218     public IClassFile getClassFile() {
219         return null;
220     }
221     /**
222      * @see IMember
223      */

224     public ICompilationUnit getCompilationUnit() {
225         return null;
226     }
227     /**
228      * Returns the info for this handle.
229      * If this element is not already open, it and all of its parents are opened.
230      * Does not return null.
231      * NOTE: BinaryType infos are NOT rooted under JavaElementInfo.
232      * @exception JavaModelException if the element is not present or not accessible
233      */

234     public Object JavaDoc getElementInfo() throws JavaModelException {
235         return getElementInfo(null);
236     }
237     /**
238      * Returns the info for this handle.
239      * If this element is not already open, it and all of its parents are opened.
240      * Does not return null.
241      * NOTE: BinaryType infos are NOT rooted under JavaElementInfo.
242      * @exception JavaModelException if the element is not present or not accessible
243      */

244     public Object JavaDoc getElementInfo(IProgressMonitor monitor) throws JavaModelException {
245
246         JavaModelManager manager = JavaModelManager.getJavaModelManager();
247         Object JavaDoc info = manager.getInfo(this);
248         if (info != null) return info;
249         return openWhenClosed(createElementInfo(), monitor);
250     }
251     /**
252      * @see IAdaptable
253      */

254     public String JavaDoc getElementName() {
255         return ""; //$NON-NLS-1$
256
}
257     /*
258      * Creates a Java element handle from the given memento.
259      * The given token is the current delimiter indicating the type of the next token(s).
260      * The given working copy owner is used only for compilation unit handles.
261      */

262     public abstract IJavaElement getHandleFromMemento(String JavaDoc token, MementoTokenizer memento, WorkingCopyOwner owner);
263     /*
264      * Creates a Java element handle from the given memento.
265      * The given working copy owner is used only for compilation unit handles.
266      */

267     public IJavaElement getHandleFromMemento(MementoTokenizer memento, WorkingCopyOwner owner) {
268         if (!memento.hasMoreTokens()) return this;
269         String JavaDoc token = memento.nextToken();
270         return getHandleFromMemento(token, memento, owner);
271     }
272     /**
273      * @see IJavaElement
274      */

275     public String JavaDoc getHandleIdentifier() {
276         return getHandleMemento();
277     }
278     /**
279      * @see JavaElement#getHandleMemento()
280      */

281     public String JavaDoc getHandleMemento(){
282         StringBuffer JavaDoc buff = new StringBuffer JavaDoc();
283         getHandleMemento(buff);
284         return buff.toString();
285     }
286     protected void getHandleMemento(StringBuffer JavaDoc buff) {
287         ((JavaElement)getParent()).getHandleMemento(buff);
288         buff.append(getHandleMementoDelimiter());
289         escapeMementoName(buff, getElementName());
290     }
291     /**
292      * Returns the <code>char</code> that marks the start of this handles
293      * contribution to a memento.
294      */

295     protected abstract char getHandleMementoDelimiter();
296     /**
297      * @see IJavaElement
298      */

299     public IJavaModel getJavaModel() {
300         IJavaElement current = this;
301         do {
302             if (current instanceof IJavaModel) return (IJavaModel) current;
303         } while ((current = current.getParent()) != null);
304         return null;
305     }
306
307     /**
308      * @see IJavaElement
309      */

310     public IJavaProject getJavaProject() {
311         IJavaElement current = this;
312         do {
313             if (current instanceof IJavaProject) return (IJavaProject) current;
314         } while ((current = current.getParent()) != null);
315         return null;
316     }
317     /*
318      * @see IJavaElement
319      */

320     public IOpenable getOpenable() {
321         return this.getOpenableParent();
322     }
323     /**
324      * Return the first instance of IOpenable in the parent
325      * hierarchy of this element.
326      *
327      * <p>Subclasses that are not IOpenable's must override this method.
328      */

329     public IOpenable getOpenableParent() {
330         return (IOpenable)this.parent;
331     }
332     /**
333      * @see IJavaElement
334      */

335     public IJavaElement getParent() {
336         return this.parent;
337     }
338     /*
339      * @see IJavaElement#getPrimaryElement()
340      */

341     public IJavaElement getPrimaryElement() {
342         return getPrimaryElement(true);
343     }
344     /*
345      * Returns the primary element. If checkOwner, and the cu owner is primary,
346      * return this element.
347      */

348     public IJavaElement getPrimaryElement(boolean checkOwner) {
349         return this;
350     }
351     /**
352      * Returns the element that is located at the given source position
353      * in this element. This is a helper method for <code>ICompilationUnit#getElementAt</code>,
354      * and only works on compilation units and types. The position given is
355      * known to be within this element's source range already, and if no finer
356      * grained element is found at the position, this element is returned.
357      */

358     protected IJavaElement getSourceElementAt(int position) throws JavaModelException {
359         if (this instanceof ISourceReference) {
360             IJavaElement[] children = getChildren();
361             for (int i = children.length-1; i >= 0; i--) {
362                 IJavaElement aChild = children[i];
363                 if (aChild instanceof SourceRefElement) {
364                     SourceRefElement child = (SourceRefElement) children[i];
365                     ISourceRange range = child.getSourceRange();
366                     int start = range.getOffset();
367                     int end = start + range.getLength();
368                     if (start <= position && position <= end) {
369                         if (child instanceof IField) {
370                             // check muti-declaration case (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=39943)
371
int declarationStart = start;
372                             SourceRefElement candidate = null;
373                             do {
374                                 // check name range
375
range = ((IField)child).getNameRange();
376                                 if (position <= range.getOffset() + range.getLength()) {
377                                     candidate = child;
378                                 } else {
379                                     return candidate == null ? child.getSourceElementAt(position) : candidate.getSourceElementAt(position);
380                                 }
381                                 child = --i>=0 ? (SourceRefElement) children[i] : null;
382                             } while (child != null && child.getSourceRange().getOffset() == declarationStart);
383                             // position in field's type: use first field
384
return candidate.getSourceElementAt(position);
385                         } else if (child instanceof IParent) {
386                             return child.getSourceElementAt(position);
387                         } else {
388                             return child;
389                         }
390                     }
391                 }
392             }
393         } else {
394             // should not happen
395
Assert.isTrue(false);
396         }
397         return this;
398     }
399     /**
400      * Returns the SourceMapper facility for this element, or
401      * <code>null</code> if this element does not have a
402      * SourceMapper.
403      */

404     public SourceMapper getSourceMapper() {
405         return ((JavaElement)getParent()).getSourceMapper();
406     }
407     /* (non-Javadoc)
408      * @see org.eclipse.jdt.core.IJavaElement#getSchedulingRule()
409      */

410     public ISchedulingRule getSchedulingRule() {
411         IResource resource = getResource();
412         if (resource == null) {
413             class NoResourceSchedulingRule implements ISchedulingRule {
414                 public IPath path;
415                 public NoResourceSchedulingRule(IPath path) {
416                     this.path = path;
417                 }
418                 public boolean contains(ISchedulingRule rule) {
419                     if (rule instanceof NoResourceSchedulingRule) {
420                         return this.path.isPrefixOf(((NoResourceSchedulingRule)rule).path);
421                     } else {
422                         return false;
423                     }
424                 }
425                 public boolean isConflicting(ISchedulingRule rule) {
426                     if (rule instanceof NoResourceSchedulingRule) {
427                         IPath otherPath = ((NoResourceSchedulingRule)rule).path;
428                         return this.path.isPrefixOf(otherPath) || otherPath.isPrefixOf(this.path);
429                     } else {
430                         return false;
431                     }
432                 }
433             }
434             return new NoResourceSchedulingRule(getPath());
435         } else {
436             return resource;
437         }
438     }
439     /**
440      * @see IParent
441      */

442     public boolean hasChildren() throws JavaModelException {
443         // if I am not open, return true to avoid opening (case of a Java project, a compilation unit or a class file).
444
// also see https://bugs.eclipse.org/bugs/show_bug.cgi?id=52474
445
Object JavaDoc elementInfo = JavaModelManager.getJavaModelManager().getInfo(this);
446         if (elementInfo instanceof JavaElementInfo) {
447             return ((JavaElementInfo)elementInfo).getChildren().length > 0;
448         } else {
449             return true;
450         }
451     }
452
453     /**
454      * Returns the hash code for this Java element. By default,
455      * the hash code for an element is a combination of its name
456      * and parent's hash code. Elements with other requirements must
457      * override this method.
458      */

459     public int hashCode() {
460         if (this.parent == null) return super.hashCode();
461         return Util.combineHashCodes(getElementName().hashCode(), this.parent.hashCode());
462     }
463     /**
464      * Returns true if this element is an ancestor of the given element,
465      * otherwise false.
466      */

467     public boolean isAncestorOf(IJavaElement e) {
468         IJavaElement parentElement= e.getParent();
469         while (parentElement != null && !parentElement.equals(this)) {
470             parentElement= parentElement.getParent();
471         }
472         return parentElement != null;
473     }
474     
475     /**
476      * @see IJavaElement
477      */

478     public boolean isReadOnly() {
479         return false;
480     }
481     /**
482      * Creates and returns a new not present exception for this element.
483      */

484     public JavaModelException newNotPresentException() {
485         return new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
486     }
487     /**
488      * Creates and returns a new Java model exception for this element with the given status.
489      */

490     public JavaModelException newJavaModelException(IStatus status) {
491         if (status instanceof IJavaModelStatus)
492             return new JavaModelException((IJavaModelStatus) status);
493         else
494             return new JavaModelException(new JavaModelStatus(status.getSeverity(), status.getCode(), status.getMessage()));
495     }
496     /*
497      * Opens an <code>Openable</code> that is known to be closed (no check for <code>isOpen()</code>).
498      * Returns the created element info.
499      */

500     protected Object JavaDoc openWhenClosed(Object JavaDoc info, IProgressMonitor monitor) throws JavaModelException {
501         JavaModelManager manager = JavaModelManager.getJavaModelManager();
502         boolean hadTemporaryCache = manager.hasTemporaryCache();
503         try {
504             HashMap JavaDoc newElements = manager.getTemporaryCache();
505             generateInfos(info, newElements, monitor);
506             if (info == null) {
507                 info = newElements.get(this);
508             }
509             if (info == null) { // a source ref element could not be opened
510
// close the buffer that was opened for the openable parent
511
// close only the openable's buffer (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=62854)
512
Openable openable = (Openable) getOpenable();
513                 if (newElements.containsKey(openable)) {
514                     openable.closeBuffer();
515                 }
516                 throw newNotPresentException();
517             }
518             if (!hadTemporaryCache) {
519                 manager.putInfos(this, newElements);
520             }
521         } finally {
522             if (!hadTemporaryCache) {
523                 manager.resetTemporaryCache();
524             }
525         }
526         return info;
527     }
528     /**
529      */

530     public String JavaDoc readableName() {
531         return this.getElementName();
532     }
533     public JavaElement resolved(Binding binding) {
534         return this;
535     }
536     public JavaElement unresolved() {
537         return this;
538     }
539     protected String JavaDoc tabString(int tab) {
540         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
541         for (int i = tab; i > 0; i--)
542             buffer.append(" "); //$NON-NLS-1$
543
return buffer.toString();
544     }
545     /**
546      * Debugging purposes
547      */

548     public String JavaDoc toDebugString() {
549         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
550         this.toStringInfo(0, buffer, NO_INFO, true/*show resolved info*/);
551         return buffer.toString();
552     }
553     /**
554      * Debugging purposes
555      */

556     public String JavaDoc toString() {
557         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
558         toString(0, buffer);
559         return buffer.toString();
560     }
561     /**
562      * Debugging purposes
563      */

564     protected void toString(int tab, StringBuffer JavaDoc buffer) {
565         Object JavaDoc info = this.toStringInfo(tab, buffer);
566         if (tab == 0) {
567             this.toStringAncestors(buffer);
568         }
569         this.toStringChildren(tab, buffer, info);
570     }
571     /**
572      * Debugging purposes
573      */

574     public String JavaDoc toStringWithAncestors() {
575         return toStringWithAncestors(true/*show resolved info*/);
576     }
577         /**
578      * Debugging purposes
579      */

580     public String JavaDoc toStringWithAncestors(boolean showResolvedInfo) {
581         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
582         this.toStringInfo(0, buffer, NO_INFO, showResolvedInfo);
583         this.toStringAncestors(buffer);
584         return buffer.toString();
585     }
586     /**
587      * Debugging purposes
588      */

589     protected void toStringAncestors(StringBuffer JavaDoc buffer) {
590         JavaElement parentElement = (JavaElement)this.getParent();
591         if (parentElement != null && parentElement.getParent() != null) {
592             buffer.append(" [in "); //$NON-NLS-1$
593
parentElement.toStringInfo(0, buffer, NO_INFO, false/*don't show resolved info*/);
594             parentElement.toStringAncestors(buffer);
595             buffer.append("]"); //$NON-NLS-1$
596
}
597     }
598     /**
599      * Debugging purposes
600      */

601     protected void toStringChildren(int tab, StringBuffer JavaDoc buffer, Object JavaDoc info) {
602         if (info == null || !(info instanceof JavaElementInfo)) return;
603         IJavaElement[] children = ((JavaElementInfo)info).getChildren();
604         for (int i = 0; i < children.length; i++) {
605             buffer.append("\n"); //$NON-NLS-1$
606
((JavaElement)children[i]).toString(tab + 1, buffer);
607         }
608     }
609     /**
610      * Debugging purposes
611      */

612     public Object JavaDoc toStringInfo(int tab, StringBuffer JavaDoc buffer) {
613         Object JavaDoc info = JavaModelManager.getJavaModelManager().peekAtInfo(this);
614         this.toStringInfo(tab, buffer, info, true/*show resolved info*/);
615         return info;
616     }
617     /**
618      * Debugging purposes
619      * @param showResolvedInfo TODO
620      */

621     protected void toStringInfo(int tab, StringBuffer JavaDoc buffer, Object JavaDoc info, boolean showResolvedInfo) {
622         buffer.append(this.tabString(tab));
623         toStringName(buffer);
624         if (info == null) {
625             buffer.append(" (not open)"); //$NON-NLS-1$
626
}
627     }
628     /**
629      * Debugging purposes
630      */

631     protected void toStringName(StringBuffer JavaDoc buffer) {
632         buffer.append(getElementName());
633     }
634     
635     protected URL JavaDoc getJavadocBaseLocation() throws JavaModelException {
636         IPackageFragmentRoot root= (IPackageFragmentRoot) this.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
637         if (root == null) {
638             return null;
639         }
640
641         if (root.getKind() == IPackageFragmentRoot.K_BINARY) {
642             IClasspathEntry entry= root.getRawClasspathEntry();
643             if (entry == null) {
644                 return null;
645             }
646             if (entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
647                 entry= getRealClasspathEntry(root.getJavaProject(), entry.getPath(), root.getPath());
648                 if (entry == null) {
649                     return null;
650                 }
651             }
652             return getLibraryJavadocLocation(entry);
653         }
654         return null;
655     }
656     
657     private static IClasspathEntry getRealClasspathEntry(IJavaProject jproject, IPath containerPath, IPath libPath) throws JavaModelException {
658         IClasspathContainer container= JavaCore.getClasspathContainer(containerPath, jproject);
659         if (container != null) {
660             IClasspathEntry[] entries= container.getClasspathEntries();
661             for (int i= 0; i < entries.length; i++) {
662                 IClasspathEntry curr = entries[i];
663                 if (curr == null) {
664                     if (JavaModelManager.CP_RESOLVE_VERBOSE) {
665                         JavaModelManager.getJavaModelManager().verbose_missbehaving_container(jproject, containerPath, entries);
666                     }
667                     break;
668                 }
669                 IClasspathEntry resolved= JavaCore.getResolvedClasspathEntry(curr);
670                 if (resolved != null && libPath.equals(resolved.getPath())) {
671                     return curr; // return the real entry
672
}
673             }
674         }
675         return null; // not found
676
}
677     
678     protected static URL JavaDoc getLibraryJavadocLocation(IClasspathEntry entry) throws JavaModelException {
679         switch(entry.getEntryKind()) {
680             case IClasspathEntry.CPE_LIBRARY :
681             case IClasspathEntry.CPE_VARIABLE :
682                 break;
683             default :
684                 throw new IllegalArgumentException JavaDoc("Entry must be of kind CPE_LIBRARY or CPE_VARIABLE"); //$NON-NLS-1$
685
}
686         
687         IClasspathAttribute[] extraAttributes= entry.getExtraAttributes();
688         for (int i= 0; i < extraAttributes.length; i++) {
689             IClasspathAttribute attrib= extraAttributes[i];
690             if (IClasspathAttribute.JAVADOC_LOCATION_ATTRIBUTE_NAME.equals(attrib.getName())) {
691                 String JavaDoc value = attrib.getValue();
692                 try {
693                     return new URL JavaDoc(value);
694                 } catch (MalformedURLException JavaDoc e) {
695                     throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.CANNOT_RETRIEVE_ATTACHED_JAVADOC, value));
696                 }
697             }
698         }
699         return null;
700     }
701     
702     /*
703      * @see IJavaElement#getAttachedJavadoc(IProgressMonitor)
704      */

705     public String JavaDoc getAttachedJavadoc(IProgressMonitor monitor) throws JavaModelException {
706         return null;
707     }
708     
709     int getIndexOf(byte[] array, byte[] toBeFound, int start) {
710         if (array == null || toBeFound == null)
711             return -1;
712         final int toBeFoundLength = toBeFound.length;
713         final int arrayLength = array.length;
714         if (arrayLength < toBeFoundLength)
715             return -1;
716         loop: for (int i = start, max = arrayLength - toBeFoundLength + 1; i < max; i++) {
717             if (array[i] == toBeFound[0]) {
718                 for (int j = 1; j < toBeFoundLength; j++) {
719                     if (array[i + j] != toBeFound[j])
720                         continue loop;
721                 }
722                 return i;
723             }
724         }
725         return -1;
726     }
727     /*
728      * We don't use getContentEncoding() on the URL connection, because it might leave open streams behind.
729      * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=117890
730      */

731     protected String JavaDoc getURLContents(String JavaDoc docUrlValue) throws JavaModelException {
732         InputStream JavaDoc stream = null;
733         JarURLConnection JavaDoc connection2 = null;
734         try {
735             URL JavaDoc docUrl = new URL JavaDoc(docUrlValue);
736             URLConnection JavaDoc connection = docUrl.openConnection();
737             if (connection instanceof JarURLConnection JavaDoc) {
738                 connection2 = (JarURLConnection JavaDoc) connection;
739                 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=156307
740
connection.setUseCaches(false);
741             }
742             stream = new BufferedInputStream JavaDoc(connection.getInputStream());
743             String JavaDoc encoding = connection.getContentEncoding();
744             byte[] contents = org.eclipse.jdt.internal.compiler.util.Util.getInputStreamAsByteArray(stream, connection.getContentLength());
745             if (encoding == null) {
746                 int index = getIndexOf(contents, CONTENT_TYPE, 0);
747                 if (index != -1) {
748                     index = getIndexOf(contents, CONTENT, index);
749                     if (index != -1) {
750                         int offset = index + CONTENT.length;
751                         int index2 = getIndexOf(contents, CLOSING_DOUBLE_QUOTE, offset);
752                         if (index2 != -1) {
753                             final int charsetIndex = getIndexOf(contents, CHARSET, offset);
754                             if (charsetIndex != -1) {
755                                 int start = charsetIndex + CHARSET.length;
756                                 encoding = new String JavaDoc(contents, start, index2 - start, "UTF-8"); //$NON-NLS-1$
757
}
758                         }
759                     }
760                 }
761             }
762             try {
763                 if (encoding == null) {
764                     encoding = this.getJavaProject().getProject().getDefaultCharset();
765                 }
766             } catch (CoreException e) {
767                 // ignore
768
}
769             if (contents != null) {
770                 if (encoding != null) {
771                     return new String JavaDoc(contents, encoding);
772                 } else {
773                     // platform encoding is used
774
return new String JavaDoc(contents);
775                 }
776             }
777         } catch (MalformedURLException JavaDoc e) {
778             throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.CANNOT_RETRIEVE_ATTACHED_JAVADOC, this));
779         } catch (FileNotFoundException JavaDoc e) {
780             // ignore. see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=120559
781
} catch(IOException JavaDoc e) {
782             StringWriter JavaDoc stringWriter = new StringWriter JavaDoc();
783             PrintWriter JavaDoc writer = new PrintWriter JavaDoc(stringWriter);
784             e.printStackTrace(writer);
785             writer.flush();
786             writer.close();
787             throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.CANNOT_RETRIEVE_ATTACHED_JAVADOC, this, String.valueOf(stringWriter.getBuffer())));
788         } finally {
789             if (stream != null) {
790                 try {
791                     stream.close();
792                 } catch (IOException JavaDoc e) {
793                     // ignore
794
}
795             }
796             if (connection2 != null) {
797                 try {
798                     connection2.getJarFile().close();
799                 } catch(IOException JavaDoc e) {
800                     // ignore
801
} catch(IllegalStateException JavaDoc e) {
802                     /*
803                      * ignore. Can happen in case the stream.close() did close the jar file
804                      * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=140750
805                      */

806                 }
807             }
808         }
809         return null;
810     }
811 }
812
Popular Tags