KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > debugger > jpda > projects > EditorContextImpl


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.debugger.jpda.projects;
21
22 import com.sun.source.tree.AssignmentTree;
23 import com.sun.source.tree.ExpressionStatementTree;
24 import com.sun.source.tree.ExpressionTree;
25 import com.sun.source.tree.Scope;
26 import com.sun.source.tree.VariableTree;
27 import com.sun.source.util.TreeScanner;
28 import java.awt.Color JavaDoc;
29 import java.beans.PropertyChangeEvent JavaDoc;
30 import java.beans.PropertyChangeListener JavaDoc;
31 import java.beans.PropertyChangeSupport JavaDoc;
32 import java.io.IOException JavaDoc;
33 import java.lang.reflect.InvocationTargetException JavaDoc;
34 import java.net.URL JavaDoc;
35 import java.net.MalformedURLException JavaDoc;
36 import java.util.ArrayList JavaDoc;
37 import java.util.Collection JavaDoc;
38 import java.util.HashMap JavaDoc;
39 import java.util.HashSet JavaDoc;
40 import java.util.Iterator JavaDoc;
41 import java.util.List JavaDoc;
42 import java.util.Map JavaDoc;
43 import java.util.Set JavaDoc;
44 import javax.swing.SwingUtilities JavaDoc;
45 import javax.swing.event.ChangeEvent JavaDoc;
46 import javax.swing.event.ChangeListener JavaDoc;
47 import javax.swing.text.BadLocationException JavaDoc;
48 import javax.swing.text.Caret JavaDoc;
49 import javax.swing.text.StyledDocument JavaDoc;
50 import javax.swing.JEditorPane JavaDoc;
51
52 import com.sun.source.tree.CompilationUnitTree;
53 import com.sun.source.tree.Tree;
54 import com.sun.source.tree.ImportTree;
55 import com.sun.source.util.SourcePositions;
56 import javax.lang.model.util.Elements;
57 import javax.lang.model.element.Element;
58 import javax.lang.model.element.ElementKind;
59 import javax.lang.model.element.TypeElement;
60 import javax.lang.model.element.VariableElement;
61 import org.netbeans.api.java.source.CancellableTask;
62 import org.netbeans.api.java.source.CompilationController;
63 import org.netbeans.api.java.source.ElementUtilities;
64 import org.netbeans.editor.Coloring;
65 import org.netbeans.modules.editor.highlights.spi.Highlight;
66
67 import org.openide.ErrorManager;
68
69 import org.openide.cookies.EditorCookie;
70 import org.openide.cookies.LineCookie;
71 import org.openide.filesystems.FileObject;
72 import org.openide.filesystems.FileStateInvalidException;
73 import org.openide.filesystems.URLMapper;
74 import org.openide.loaders.DataObject;
75 import org.openide.loaders.DataShadow;
76 import org.openide.loaders.DataObjectNotFoundException;
77 import org.openide.nodes.Node;
78 import org.openide.text.Line;
79 import org.openide.text.NbDocument;
80 import org.openide.util.Lookup;
81 import org.openide.util.LookupEvent;
82 import org.openide.util.LookupListener;
83 import org.openide.util.Utilities;
84 import org.openide.windows.TopComponent;
85 import org.netbeans.api.java.source.JavaSource;
86 import org.netbeans.api.java.source.JavaSource.Phase;
87 import org.netbeans.api.java.source.SourceUtils;
88
89 import org.netbeans.spi.debugger.jpda.EditorContext;
90
91 /**
92  *
93  * @author Jan Jancura
94  */

95 public class EditorContextImpl extends EditorContext {
96     
97     private static String JavaDoc fronting =
98         System.getProperty ("netbeans.debugger.fronting");
99     
100     private PropertyChangeSupport JavaDoc pcs;
101     private Map JavaDoc annotationToURL = new HashMap JavaDoc ();
102     private ChangeListener JavaDoc changedFilesListener;
103     private Map JavaDoc timeStampToRegistry = new HashMap JavaDoc ();
104     private Set JavaDoc modifiedDataObjects;
105     private PropertyChangeListener JavaDoc editorObservableListener;
106
107     private Lookup.Result resDataObject;
108     private Lookup.Result resEditorCookie;
109     private Lookup.Result resNode;
110
111     private Object JavaDoc currentLock = new Object JavaDoc();
112     private String JavaDoc currentURL = null;
113     //private Element currentElement = null;
114
private EditorCookie currentEditorCookie = null;
115     
116     
117     {
118         pcs = new PropertyChangeSupport JavaDoc (this);
119
120         resDataObject = Utilities.actionsGlobalContext().lookup(new Lookup.Template(DataObject.class));
121         resDataObject.addLookupListener(new EditorLookupListener(DataObject.class));
122
123         resEditorCookie = Utilities.actionsGlobalContext().lookup(new Lookup.Template(EditorCookie.class));
124         resEditorCookie.addLookupListener(new EditorLookupListener(EditorCookie.class));
125
126         resNode = Utilities.actionsGlobalContext().lookup(new Lookup.Template(Node.class));
127         resNode.addLookupListener(new EditorLookupListener(Node.class));
128
129     }
130     
131     
132     /**
133      * Shows source with given url on given line number.
134      *
135      * @param url a url of source to be shown
136      * @param lineNumber a number of line to be shown
137      * @param timeStamp a time stamp to be used
138      */

139     public boolean showSource (String JavaDoc url, int lineNumber, Object JavaDoc timeStamp) {
140         Line l = getLine (url, lineNumber, timeStamp); // false = use original ln
141
if (l == null) {
142             ErrorManager.getDefault().log(ErrorManager.WARNING,
143                     "Show Source: Have no line for URL = "+url+", line number = "+lineNumber);
144             return false;
145         }
146         if (fronting != null) {
147             if (fronting.equals ("true"))
148                 l.show (Line.SHOW_TOFRONT); //FIX 47825
149
else
150                 l.show (Line.SHOW_GOTO);
151             return true;
152         }
153         if (Utilities.isWindows())
154             l.show (Line.SHOW_TOFRONT); //FIX 47825
155
else
156             l.show (Line.SHOW_GOTO);
157         return true;
158     }
159     
160     /**
161      * Shows source with given url on given line number.
162      *
163      * @param url a url of source to be shown
164      * @param lineNumber a number of line to be shown
165      * @param timeStamp a time stamp to be used
166      */

167     public boolean showSource (String JavaDoc url, int lineNumber, int column, int length, Object JavaDoc timeStamp) {
168         Line l = getLine (url, lineNumber, timeStamp); // false = use original ln
169
if (l == null) {
170             ErrorManager.getDefault().log(ErrorManager.WARNING,
171                     "Show Source: Have no line for URL = "+url+", line number = "+lineNumber);
172             return false;
173         }
174         if (fronting != null) {
175             if (fronting.equals ("true"))
176                 l.show (Line.SHOW_TOFRONT, column); //FIX 47825
177
else
178                 l.show (Line.SHOW_GOTO, column);
179             return true;
180         }
181         if (Utilities.isWindows())
182             l.show (Line.SHOW_TOFRONT, column); //FIX 47825
183
else
184             l.show (Line.SHOW_GOTO, column);
185         return true;
186     }
187     
188     
189     /**
190      * Creates a new time stamp.
191      *
192      * @param timeStamp a new time stamp
193      */

194     public void createTimeStamp (Object JavaDoc timeStamp) {
195         modifiedDataObjects = new HashSet JavaDoc (
196             DataObject.getRegistry ().getModifiedSet ()
197         );
198         Registry r = new Registry ();
199         timeStampToRegistry.put (timeStamp, r);
200         Iterator JavaDoc i = modifiedDataObjects.iterator ();
201         while (i.hasNext ())
202             r.register ((DataObject) i.next ());
203         if (changedFilesListener == null) {
204             changedFilesListener = new ChangedFilesListener ();
205             DataObject.getRegistry ().addChangeListener (changedFilesListener);
206         }
207     }
208
209     /**
210      * Disposes given time stamp.
211      *
212      * @param timeStamp a time stamp to be disposed
213      */

214     public void disposeTimeStamp (Object JavaDoc timeStamp) {
215         timeStampToRegistry.remove (timeStamp);
216         if (timeStampToRegistry.isEmpty ()) {
217             DataObject.getRegistry ().removeChangeListener (changedFilesListener);
218             changedFilesListener = null;
219         }
220     }
221     
222     public Object JavaDoc annotate (
223         String JavaDoc url,
224         int lineNumber,
225         String JavaDoc annotationType,
226         Object JavaDoc timeStamp
227     ) {
228         Line l = getLine (
229             url,
230             lineNumber,
231             timeStamp
232         );
233         if (l == null) return null;
234         DebuggerAnnotation annotation =
235             new DebuggerAnnotation (annotationType, l);
236         annotationToURL.put (annotation, url);
237         
238         return annotation;
239     }
240
241     public Object JavaDoc annotate (
242         String JavaDoc url,
243         int startPosition,
244         int endPosition,
245         String JavaDoc annotationType,
246         Object JavaDoc timeStamp
247     ) {
248         Coloring coloring;
249         if (EditorContext.CURRENT_LAST_OPERATION_ANNOTATION_TYPE.equals(annotationType)) {
250             coloring = new Coloring(null, Coloring.FONT_MODE_DEFAULT, null, null, getColor(annotationType), null, null);
251         } else {
252             coloring = new Coloring(null, null, getColor(annotationType));
253         }
254         Highlight highlight = new OperationHighlight(coloring, startPosition, endPosition);
255         DebuggerAnnotation annotation;
256         try {
257             annotation = new DebuggerAnnotation(annotationType, highlight, URLMapper.findFileObject(new URL JavaDoc(url)));
258         } catch (MalformedURLException JavaDoc ex) {
259             RuntimeException JavaDoc rex = new RuntimeException JavaDoc("Bad URL: "+url);
260             rex.initCause(ex);
261             throw rex;
262         }
263         annotationToURL.put (annotation, url);
264         
265         return annotation;
266     }
267     
268     private static Color JavaDoc getColor(String JavaDoc annotationType) {
269         if (EditorContext.BREAKPOINT_ANNOTATION_TYPE.equals(annotationType)) {
270             return new Color JavaDoc(0xFC9D9F);
271         } else if (EditorContext.CURRENT_LINE_ANNOTATION_TYPE.equals(annotationType) ||
272                    EditorContext.CURRENT_OUT_OPERATION_ANNOTATION_TYPE.equals(annotationType)) {
273             return new Color JavaDoc(0xBDE6AA);
274         } else if (EditorContext.CURRENT_EXPRESSION_CURRENT_LINE_ANNOTATION_TYPE.equals(annotationType)) {
275             return new Color JavaDoc(0xE9FFE6); // 0xE3FFD2// 0xD1FFBC
276
} else if (EditorContext.CURRENT_LAST_OPERATION_ANNOTATION_TYPE.equals(annotationType)) {
277             return new Color JavaDoc(0x99BB8A);
278         } else {
279             return new Color JavaDoc(0x0000FF);
280         }
281     }
282
283     /**
284      * Removes given annotation.
285      *
286      * @return true if annotation has been successfully removed
287      */

288     public void removeAnnotation (
289         Object JavaDoc a
290     ) {
291         if (a instanceof Collection JavaDoc) {
292             Collection JavaDoc annotations = ((Collection JavaDoc) a);
293             for (Iterator JavaDoc it = annotations.iterator(); it.hasNext(); ) {
294                 removeAnnotation((DebuggerAnnotation) it.next());
295             }
296         } else {
297             removeAnnotation((DebuggerAnnotation) a);
298         }
299     }
300     
301     private void removeAnnotation(DebuggerAnnotation annotation) {
302         annotation.detach ();
303         
304         if (annotationToURL.remove (annotation) == null) {
305             return; // ??
306
}
307     }
308
309     /**
310      * Returns line number given annotation is associated with.
311      *
312      * @param annotation a annotation
313      * @param timeStamp a time stamp to be used
314      *
315      * @return line number given annotation is associated with
316      */

317     public int getLineNumber (
318         Object JavaDoc annotation,
319         Object JavaDoc timeStamp
320     ) {
321         DebuggerAnnotation a = (DebuggerAnnotation) annotation;
322         if (timeStamp == null)
323             return a.getLine ().getLineNumber () + 1;
324         String JavaDoc url = (String JavaDoc) annotationToURL.get (a);
325         Line.Set lineSet = getLineSet (url, timeStamp);
326         return lineSet.getOriginalLineNumber (a.getLine ()) + 1;
327     }
328     
329     /**
330      * Updates timeStamp for gived url.
331      *
332      * @param timeStamp time stamp to be updated
333      * @param url an url
334      */

335     public void updateTimeStamp (Object JavaDoc timeStamp, String JavaDoc url) {
336         Registry registry = (Registry) timeStampToRegistry.get (timeStamp);
337         registry.register (getDataObject (url));
338     }
339
340     /**
341      * Returns number of line currently selected in editor or <code>-1</code>.
342      *
343      * @return number of line currently selected in editor or <code>-1</code>
344      */

345     public int getCurrentLineNumber () {
346         if (SwingUtilities.isEventDispatchThread()) {
347             return getCurrentLineNumber_();
348         } else {
349             final int[] ln = new int[1];
350             try {
351                 SwingUtilities.invokeAndWait(new Runnable JavaDoc() {
352                     public void run() {
353                         ln[0] = getCurrentLineNumber_();
354                     }
355                 });
356             } catch (InvocationTargetException JavaDoc ex) {
357                 ErrorManager.getDefault().notify(ex.getTargetException());
358             } catch (InterruptedException JavaDoc ex) {
359                 ErrorManager.getDefault().notify(ex);
360             }
361             return ln[0];
362         }
363     }
364     
365     private int getCurrentLineNumber_() {
366         EditorCookie e = getCurrentEditorCookie ();
367         if (e == null) return -1;
368         JEditorPane JavaDoc ep = getCurrentEditor ();
369         if (ep == null) return -1;
370         StyledDocument JavaDoc d = e.getDocument ();
371         if (d == null) return -1;
372         Caret JavaDoc caret = ep.getCaret ();
373         if (caret == null) return -1;
374         int ln = NbDocument.findLineNumber (
375             d,
376             caret.getDot ()
377         );
378         return ln + 1;
379     }
380     
381     /**
382      * Returns name of class currently selected in editor or empty string.
383      *
384      * @return name of class currently selected in editor or empty string
385      */

386     public String JavaDoc getCurrentClassName () {
387         String JavaDoc currentClass = getCurrentElement(ElementKind.CLASS);
388         if (currentClass == null) return "";
389         else return currentClass;
390     }
391
392     /**
393      * Returns URL of source currently selected in editor or empty string.
394      *
395      * @return URL of source currently selected in editor or empty string
396      */

397     public String JavaDoc getCurrentURL () {
398         synchronized (currentLock) {
399             if (currentURL == null) {
400                 DataObject[] nodes = (DataObject[])resDataObject.allInstances().toArray(new DataObject[0]);
401
402                 currentURL = "";
403                 if (nodes.length != 1)
404                     return currentURL;
405                 
406                 DataObject dO = nodes[0];
407                 if (dO instanceof DataShadow)
408                     dO = ((DataShadow) dO).getOriginal ();
409
410                 try {
411                     currentURL = dO.getPrimaryFile ().getURL ().toString ();
412                 } catch (FileStateInvalidException ex) {
413                     //noop
414
}
415             }
416
417             return currentURL;
418         }
419     }
420
421     /**
422      * Returns name of method currently selected in editor or empty string.
423      *
424      * @return name of method currently selected in editor or empty string
425      */

426     public String JavaDoc getCurrentMethodName () {
427         String JavaDoc currentMethod = getCurrentElement(ElementKind.METHOD);
428         if (currentMethod == null) return "";
429         else return currentMethod;
430     }
431
432     /**
433      * Returns name of field currently selected in editor or <code>null</code>.
434      *
435      * @return name of field currently selected in editor or <code>null</code>
436      */

437     public String JavaDoc getCurrentFieldName () {
438         String JavaDoc currentField = getCurrentElement(ElementKind.FIELD);
439         if (currentField == null) return "";
440         else return currentField;
441         //return getSelectedIdentifier ();
442
}
443
444     /**
445      * Returns identifier currently selected in editor or <code>null</code>.
446      *
447      * @return identifier currently selected in editor or <code>null</code>
448      */

449     public String JavaDoc getSelectedIdentifier () {
450         if (SwingUtilities.isEventDispatchThread()) {
451             return getSelectedIdentifier_();
452         } else {
453             final String JavaDoc[] si = new String JavaDoc[1];
454             try {
455                 SwingUtilities.invokeAndWait(new Runnable JavaDoc() {
456                     public void run() {
457                         si[0] = getSelectedIdentifier_();
458                     }
459                 });
460             } catch (InvocationTargetException JavaDoc ex) {
461                 ErrorManager.getDefault().notify(ex.getTargetException());
462             } catch (InterruptedException JavaDoc ex) {
463                 ErrorManager.getDefault().notify(ex);
464             }
465             return si[0];
466         }
467     }
468
469     private String JavaDoc getSelectedIdentifier_() {
470         JEditorPane JavaDoc ep = getCurrentEditor ();
471         if (ep == null) return null;
472         String JavaDoc s = ep.getSelectedText ();
473         if (s == null) return null;
474         if (Utilities.isJavaIdentifier (s)) return s;
475         return null;
476     }
477
478     /**
479      * Returns method name currently selected in editor or empty string.
480      *
481      * @return method name currently selected in editor or empty string
482      */

483     public String JavaDoc getSelectedMethodName () {
484         if (SwingUtilities.isEventDispatchThread()) {
485             return getSelectedMethodName_();
486         } else {
487             final String JavaDoc[] mn = new String JavaDoc[1];
488             try {
489                 SwingUtilities.invokeAndWait(new Runnable JavaDoc() {
490                     public void run() {
491                         mn[0] = getSelectedMethodName_();
492                     }
493                 });
494             } catch (InvocationTargetException JavaDoc ex) {
495                 ErrorManager.getDefault().notify(ex.getTargetException());
496             } catch (InterruptedException JavaDoc ex) {
497                 ErrorManager.getDefault().notify(ex);
498             }
499             return mn[0];
500         }
501     }
502     
503     private String JavaDoc getSelectedMethodName_() {
504         EditorCookie e = getCurrentEditorCookie ();
505         if (e == null) return "";
506         JEditorPane JavaDoc ep = getCurrentEditor ();
507         if (ep == null) return "";
508         StyledDocument JavaDoc doc = e.getDocument ();
509         if (doc == null) return "";
510         int offset = ep.getCaret ().getDot ();
511         String JavaDoc t = null;
512 // if ( (ep.getSelectionStart () <= offset) &&
513
// (offset <= ep.getSelectionEnd ())
514
// ) t = ep.getSelectedText ();
515
// if (t != null) return t;
516

517         int line = NbDocument.findLineNumber (
518             doc,
519             offset
520         );
521         int col = NbDocument.findLineColumn (
522             doc,
523             offset
524         );
525         try {
526             javax.swing.text.Element JavaDoc lineElem =
527                 org.openide.text.NbDocument.findLineRootElement (doc).
528                 getElement (line);
529
530             if (lineElem == null) return "";
531             int lineStartOffset = lineElem.getStartOffset ();
532             int lineLen = lineElem.getEndOffset () - lineStartOffset;
533             // t contains current line in editor
534
t = doc.getText (lineStartOffset, lineLen);
535             
536             int identStart = col;
537             while ( identStart > 0 &&
538                     Character.isJavaIdentifierPart (
539                         t.charAt (identStart - 1)
540                     )
541             ) identStart--;
542
543             int identEnd = col;
544             while (identEnd < lineLen &&
545                    Character.isJavaIdentifierPart (t.charAt (identEnd))
546             ) {
547                 identEnd++;
548             }
549             int i = t.indexOf ('(', identEnd);
550             if (i < 0) return "";
551             if (t.substring (identEnd, i).trim ().length () > 0) return "";
552
553             if (identStart == identEnd) return "";
554             return t.substring (identStart, identEnd);
555         } catch (javax.swing.text.BadLocationException JavaDoc ex) {
556             return "";
557         }
558     }
559     
560     /*
561     private ClassTree findClassTree(List typeDecls, String className) {
562         for (Iterator it = typeDecls.iterator(); it.hasNext(); ) {
563             Tree declTree = (Tree) it.next();
564             if (declTree instanceof ClassTree) {
565                 ClassTree ctree = (ClassTree) declTree;
566                 if (ctree.getSimpleName().equals(className)) {
567                     return ctree;
568                 } else {
569                     return findClassTree(ctree.getMemberDecls(), className);
570                 }
571             }
572         }
573         return null;
574     }
575      */

576     
577     /**
578      * Returns line number of given field in given class.
579      *
580      * @param url the url of file the class is deined in
581      * @param className the name of class (or innerclass) the field is
582      * defined in
583      * @param fieldName the name of field
584      *
585      * @return line number or -1
586      */

587     public int getFieldLineNumber (
588         String JavaDoc url,
589         final String JavaDoc className,
590         final String JavaDoc fieldName
591     ) {
592         final DataObject dataObject = getDataObject (url);
593         if (dataObject == null) return -1;
594         JavaSource js = JavaSource.forFileObject(dataObject.getPrimaryFile());
595         if (js == null) return -1;
596         final int[] result = new int[] {-1};
597         
598         try {
599             js.runUserActionTask(new CancellableTask<CompilationController>() {
600                 public void cancel() {
601                 }
602                 public void run(CompilationController ci) throws Exception JavaDoc {
603                     Elements elms = ci.getElements();
604                     TypeElement classElement = elms.getTypeElement(className);
605                     if (classElement == null) return ;
606                     List JavaDoc classMemberElements = elms.getAllMembers(classElement);
607                     for (Iterator JavaDoc it = classMemberElements.iterator(); it.hasNext(); ) {
608                         Element elm = (Element) it.next();
609                         if (elm.getKind() == ElementKind.FIELD) {
610                             String JavaDoc name = ((VariableElement) elm).getSimpleName().toString();
611                             if (name.equals(fieldName)) {
612                                 SourcePositions positions = ci.getTrees().getSourcePositions();
613                                 Tree tree = SourceUtils.treeFor(ci, elm);
614                                 int pos = (int)positions.getStartPosition(ci.getCompilationUnit(), tree);
615                                 EditorCookie editor = (EditorCookie) dataObject.getCookie(EditorCookie.class);
616                                 result[0] = NbDocument.findLineNumber(editor.getDocument(), pos);
617                                 //return elms.getSourcePosition(elm).getLine();
618
}
619                         }
620                     }
621                 }
622             },true);
623         } catch (IOException JavaDoc ioex) {
624             //XXX: log the exception?
625
return -1;
626         }
627         return result[0];
628         /*
629         CompilationUnitTree cutree = ci.getTree();
630         if (cutree == null) return -1;
631         List typeDecls = cutree.getTypeDecls();
632         ClassTree ctree = findClassTree(typeDecls, className);
633         */

634         /*
635         Elements elms = ci.getElements();
636         SourceCookie.Editor sc = (SourceCookie.Editor) dataObject.getCookie
637             (SourceCookie.Editor.class);
638         if (sc == null) return -1;
639         sc.open ();
640         StyledDocument sd = sc.getDocument ();
641         if (sd == null) return -1;
642         ClassElement[] classes = sc.getSource ().getAllClasses ();
643         FieldElement fe = null;
644         int i, k = classes.length;
645         for (i = 0; i < k; i++)
646             if (classes [i].getName ().getFullName ().equals (className)) {
647                 fe = classes [i].getField (Identifier.create (fieldName));
648                 break;
649             }
650         if (fe == null) return -1;
651         int position = sc.sourceToText (fe).getStartOffset ();
652         return NbDocument.findLineNumber (sd, position) + 1;
653          */

654     }
655     
656     /**
657      * Returns binary class name for given url and line number or null.
658      *
659      * @param url a url
660      * @param lineNumber a line number
661      *
662      * @return binary class name for given url and line number or null
663      */

664     public String JavaDoc getClassName (
665         String JavaDoc url,
666         int lineNumber
667     ) {
668         DataObject dataObject = getDataObject (url);
669         if (dataObject == null) return null;
670         JavaSource js = JavaSource.forFileObject(dataObject.getPrimaryFile());
671         if (js == null) return "";
672         EditorCookie ec = (EditorCookie) dataObject.getCookie(EditorCookie.class);
673         if (ec == null) return "";
674         StyledDocument JavaDoc doc;
675         try {
676             doc = ec.openDocument();
677         } catch (IOException JavaDoc ex) {
678             return "";
679         }
680         try {
681             final int offset = NbDocument.findLineOffset(doc, lineNumber - 1);
682             final String JavaDoc[] result = new String JavaDoc[] {""};
683             js.runUserActionTask(new CancellableTask<CompilationController>() {
684                 public void cancel() {
685                 }
686                 public void run(CompilationController ci) throws Exception JavaDoc {
687                     if (ci.toPhase(Phase.RESOLVED).compareTo(Phase.RESOLVED) < 0) //TODO: ELEMENTS_RESOLVED may be sufficient
688
return;
689                     
690                     Scope scope = ci.getTreeUtilities().scopeFor(offset);
691                     TypeElement te = scope.getEnclosingClass();
692                     result[0] = ElementUtilities.getBinaryName(te);
693                 }
694             }, true);
695             return result[0];
696         } catch (IOException JavaDoc ioex) {
697             //XXX: log the exception?
698
return "";
699         } catch (IndexOutOfBoundsException JavaDoc ioobex) {
700             //XXX: log the exception?
701
return null;
702         }
703         /*
704         SourceCookie.Editor sc = (SourceCookie.Editor) dataObject.getCookie
705             (SourceCookie.Editor.class);
706         if (sc == null) return null;
707         StyledDocument sd = null;
708         try {
709             sd = sc.openDocument ();
710         } catch (IOException ex) {
711         }
712         if (sd == null) return null;
713         int offset;
714         try {
715             offset = NbDocument.findLineOffset (sd, lineNumber - 1);
716         } catch (IndexOutOfBoundsException ioobex) {
717             return null;
718         }
719         Element element = sc.findElement (offset);
720         
721         if (element == null) return "";
722         if (element instanceof ClassElement)
723             return getClassName ((ClassElement) element);
724         if (element instanceof ConstructorElement)
725             return getClassName (((ConstructorElement) element).getDeclaringClass ());
726         if (element instanceof FieldElement)
727             return getClassName (((FieldElement) element).getDeclaringClass ());
728         if (element instanceof InitializerElement)
729             return getClassName (((InitializerElement) element).getDeclaringClass());
730         return "";
731          */

732     }
733         
734     
735     public Operation[] getOperations(String JavaDoc url, final int lineNumber,
736                                      final BytecodeProvider bytecodeProvider) {
737         DataObject dataObject = getDataObject (url);
738         if (dataObject == null) return null;
739         JavaSource js = JavaSource.forFileObject(dataObject.getPrimaryFile());
740         if (js == null) return null;
741         EditorCookie ec = (EditorCookie) dataObject.getCookie(EditorCookie.class);
742         if (ec == null) return null;
743         final StyledDocument JavaDoc doc;
744         try {
745             doc = ec.openDocument();
746         } catch (IOException JavaDoc ex) {
747             return null;
748         }
749         final int offset = findLineOffset(doc, (int) lineNumber);
750         final Operation ops[][] = new Operation[1][];
751         try {
752             js.runUserActionTask(new CancellableTask<CompilationController>() {
753                 public void cancel() {
754                 }
755                 public void run(CompilationController ci) throws Exception JavaDoc {
756                     if (ci.toPhase(Phase.RESOLVED).compareTo(Phase.RESOLVED) < 0) //TODO: ELEMENTS_RESOLVED may be sufficient
757
return;
758                     
759                     Scope scope = ci.getTreeUtilities().scopeFor(offset);
760                     Element method = scope.getEnclosingMethod();
761                     if (method == null) {
762                         ops[0] = new Operation[] {};
763                         return ;
764                     }
765                     Tree methodTree = SourceUtils.treeFor(ci, method);
766                     CompilationUnitTree cu = ci.getCompilationUnit();
767                     ExpressionScanner scanner = new ExpressionScanner(lineNumber, cu, ci.getTrees().getSourcePositions());
768                     ExpressionScanner.ExpressionsInfo info = new ExpressionScanner.ExpressionsInfo();
769                     List JavaDoc<Tree> expTrees = methodTree.accept(scanner, info);
770                     
771                     //com.sun.source.tree.ExpressionTree expTree = scanner.getExpressionTree();
772
if (expTrees == null || expTrees.size() == 0) {
773                         ops[0] = new Operation[] {};
774                         return ;
775                     }
776                     //Tree[] expTrees = expTreeSet.toArray(new Tree[0]);
777
SourcePositions sp = ci.getTrees().getSourcePositions();
778                     int treeStartLine =
779                             (int) cu.getLineMap().getLineNumber(
780                                 sp.getStartPosition(cu, expTrees.get(0)));
781                     int treeEndLine =
782                             (int) cu.getLineMap().getLineNumber(
783                                 sp.getEndPosition(cu, expTrees.get(expTrees.size() - 1)));
784                     
785                     int[] indexes = bytecodeProvider.indexAtLines(treeStartLine, treeEndLine);
786                     if (indexes == null) {
787                         return ;
788                     }
789                     Map JavaDoc<Tree, Operation> nodeOperations = new HashMap JavaDoc<Tree, Operation>();
790                     ops[0] = AST2Bytecode.matchSourceTree2Bytecode(
791                             cu,
792                             ci,
793                             expTrees, info, bytecodeProvider.byteCodes(),
794                             indexes,
795                             bytecodeProvider.constantPool(),
796                             new OperationCreationDelegateImpl(),
797                             nodeOperations);
798                     if (ops[0] != null) {
799                         assignNextOperations(methodTree, cu, ci, bytecodeProvider, expTrees, info, nodeOperations);
800                     }
801                 }
802             },true);
803         } catch (IOException JavaDoc ioex) {
804             ErrorManager.getDefault().notify(ioex);
805             return null;
806         }
807         return ops[0];
808     }
809     
810     private void assignNextOperations(Tree methodTree,
811                                       CompilationUnitTree cu,
812                                       CompilationController ci,
813                                       BytecodeProvider bytecodeProvider,
814                                       List JavaDoc<Tree> treeNodes,
815                                       ExpressionScanner.ExpressionsInfo info,
816                                       Map JavaDoc<Tree, Operation> nodeOperations) {
817         int length = treeNodes.size();
818         for (int treeIndex = 0; treeIndex < length; treeIndex++) {
819             Tree node = treeNodes.get(treeIndex);
820             Set JavaDoc<Tree> nextNodes = info.getNextExpressions(node);
821             if (nextNodes != null) {
822                 EditorContext.Operation op = nodeOperations.get(node);
823                 if (op == null) {
824                     for (int backIndex = treeIndex - 1; backIndex >= 0; backIndex--) {
825                         node = treeNodes.get(backIndex);
826                         op = nodeOperations.get(node);
827                         if (op != null) break;
828                     }
829                 }
830                 if (op != null) {
831                     for (Tree t : nextNodes) {
832                         EditorContext.Operation nextOp = nodeOperations.get(t);
833                         if (nextOp == null) {
834                             SourcePositions sp = ci.getTrees().getSourcePositions();
835                             int treeStartLine =
836                                     (int) cu.getLineMap().getLineNumber(
837                                         sp.getStartPosition(cu, t));
838                             ExpressionScanner scanner = new ExpressionScanner(treeStartLine, cu, ci.getTrees().getSourcePositions());
839                             ExpressionScanner.ExpressionsInfo newInfo = new ExpressionScanner.ExpressionsInfo();
840                             List JavaDoc<Tree> newExpTrees = methodTree.accept(scanner, newInfo);
841                             treeStartLine =
842                                     (int) cu.getLineMap().getLineNumber(
843                                         sp.getStartPosition(cu, newExpTrees.get(0)));
844                             int treeEndLine =
845                                     (int) cu.getLineMap().getLineNumber(
846                                         sp.getEndPosition(cu, newExpTrees.get(newExpTrees.size() - 1)));
847
848                             int[] indexes = bytecodeProvider.indexAtLines(treeStartLine, treeEndLine);
849                             Map JavaDoc<Tree, Operation> newNodeOperations = new HashMap JavaDoc<Tree, Operation>();
850                             Operation[] newOps = AST2Bytecode.matchSourceTree2Bytecode(
851                                     cu,
852                                     ci,
853                                     newExpTrees, newInfo, bytecodeProvider.byteCodes(),
854                                     indexes,
855                                     bytecodeProvider.constantPool(),
856                                     new OperationCreationDelegateImpl(),
857                                     newNodeOperations);
858                             nextOp = newNodeOperations.get(t);
859                             if (nextOp == null) {
860                                 // Next operation not found
861
System.err.println("Next operation not found!");
862                                 continue;
863                             }
864                         }
865                         addNextOperationTo(op, nextOp);
866                     }
867                 }
868             }
869         }
870         
871     }
872     
873     /** return the offset of the first non-whitespace character on the line,
874                or -1 when the line does not exist
875      */

876     private static int findLineOffset(StyledDocument JavaDoc doc, int lineNumber) {
877         int offset;
878         try {
879             offset = NbDocument.findLineOffset (doc, lineNumber - 1);
880             int offset2 = NbDocument.findLineOffset (doc, lineNumber);
881             try {
882                 String JavaDoc lineStr = doc.getText(offset, offset2 - offset);
883                 for (int i = 0; i < lineStr.length(); i++) {
884                     if (!Character.isWhitespace(lineStr.charAt(i))) {
885                         offset += i;
886                         break;
887                     }
888                 }
889             } catch (BadLocationException JavaDoc ex) {
890                 // ignore
891
}
892         } catch (IndexOutOfBoundsException JavaDoc ioobex) {
893             return -1;
894         }
895         return offset;
896     }
897     
898     /**
899      * Returns list of imports for given source url.
900      *
901      * @param url the url of source file
902      *
903      * @return list of imports for given source url
904      */

905     public String JavaDoc[] getImports (
906         String JavaDoc url
907     ) {
908         DataObject dataObject = getDataObject (url);
909         if (dataObject == null) return new String JavaDoc [0];
910         JavaSource js = JavaSource.forFileObject(dataObject.getPrimaryFile());
911         if (js == null) return new String JavaDoc [0];
912         final List JavaDoc<String JavaDoc> imports = new ArrayList JavaDoc<String JavaDoc>();
913         try {
914             js.runUserActionTask(new CancellableTask<CompilationController>() {
915                 public void cancel() {
916                 }
917                 public void run(CompilationController ci) throws Exception JavaDoc {
918                     if (ci.toPhase(Phase.PARSED).compareTo(Phase.PARSED) < 0)
919                         return;
920                     
921                     List JavaDoc importDecl = ci.getCompilationUnit().getImports();
922                     int i = 0;
923                     for (Iterator JavaDoc it = importDecl.iterator(); it.hasNext(); i++) {
924                         ImportTree itree = (ImportTree) it.next();
925                         String JavaDoc importStr = itree.getQualifiedIdentifier().toString();
926                         imports.add(importStr);
927                     }
928                 }
929             }, true);
930         } catch (IOException JavaDoc ioex) {
931             return new String JavaDoc [0];
932         }
933         return imports.toArray(new String JavaDoc[0]);
934         /*
935         SourceCookie.Editor sc = (SourceCookie.Editor) dataObject.getCookie
936             (SourceCookie.Editor.class);
937         if (sc == null) return new String [0];
938         Import[] is = sc.getSource ().getImports ();
939         int i, k = is.length;
940         String[] is2 = new String [k];
941         for (i = 0; i < k; i++)
942             is2 [i] = is [i].getIdentifier ().getFullName ();
943         return is2;
944          */

945     }
946     
947     /**
948      * Adds a property change listener.
949      *
950      * @param l the listener to add
951      */

952     public void addPropertyChangeListener (PropertyChangeListener JavaDoc l) {
953         pcs.addPropertyChangeListener (l);
954     }
955     
956     /**
957      * Removes a property change listener.
958      *
959      * @param l the listener to remove
960      */

961     public void removePropertyChangeListener (PropertyChangeListener JavaDoc l) {
962         pcs.removePropertyChangeListener (l);
963     }
964     
965     /**
966      * Adds a property change listener.
967      *
968      * @param propertyName the name of property
969      * @param l the listener to add
970      */

971     public void addPropertyChangeListener (
972         String JavaDoc propertyName,
973         PropertyChangeListener JavaDoc l
974     ) {
975         pcs.addPropertyChangeListener (propertyName, l);
976     }
977     
978     /**
979      * Removes a property change listener.
980      *
981      * @param propertyName the name of property
982      * @param l the listener to remove
983      */

984     public void removePropertyChangeListener (
985         String JavaDoc propertyName,
986         PropertyChangeListener JavaDoc l
987     ) {
988         pcs.removePropertyChangeListener (propertyName, l);
989     }
990
991     
992     // private helper methods ..................................................
993

994 // public void fileChanged (FileEvent fe) {
995
// pcs.firePropertyChange (PROP_LINE_NUMBER, null, null);
996
// }
997
//
998
// public void fileDeleted (FileEvent fe) {}
999
// public void fileAttributeChanged (org.openide.filesystems.FileAttributeEvent fe) {}
1000
// public void fileDataCreated (FileEvent fe) {}
1001
// public void fileFolderCreated (FileEvent fe) {}
1002
// public void fileRenamed (org.openide.filesystems.FileRenameEvent fe) {}
1003

1004    
1005    private String JavaDoc getCurrentElement(final ElementKind kind) {
1006        Node[] nodes = TopComponent.getRegistry ().getCurrentNodes ();
1007        if (nodes == null) return null;
1008        if (nodes.length != 1) return null;
1009        DataObject dataObject = nodes[0].getCookie(DataObject.class);
1010        if (dataObject == null) return null;
1011        JavaSource js = JavaSource.forFileObject(dataObject.getPrimaryFile());
1012        if (js == null) return null;
1013        // TODO: Can be called outside of AWT? Probably need invokeAndWait()
1014
final int offset = org.netbeans.editor.Registry.getMostActiveComponent().getCaretPosition();
1015        final String JavaDoc[] currentElementPtr = new String JavaDoc[] { null };
1016        try {
1017            js.runUserActionTask(new CancellableTask<CompilationController>() {
1018                public void cancel() {
1019                }
1020                public void run(CompilationController ci) throws Exception JavaDoc {
1021                    if (ci.toPhase(Phase.RESOLVED).compareTo(Phase.RESOLVED) < 0) //TODO: ELEMENTS_RESOLVED may be sufficient
1022
return;
1023
1024                    if (kind == ElementKind.CLASS) {
1025                        Scope scope = ci.getTreeUtilities().scopeFor(offset);
1026                        TypeElement te = scope.getEnclosingClass();
1027                        if (te != null) {
1028                            currentElementPtr[0] = ElementUtilities.getBinaryName(te);
1029                        }
1030                    } else if (kind == ElementKind.METHOD) {
1031                        Scope scope = ci.getTreeUtilities().scopeFor(offset);
1032                        Element el = scope.getEnclosingMethod();
1033                        if (el != null) {
1034                            currentElementPtr[0] = el.getSimpleName().toString();
1035                        }
1036                    } else if (kind == ElementKind.FIELD) {
1037                        Element el = ci.getTrees().getElement(ci.getTreeUtilities().pathFor(offset));
1038                        if (el != null && el.getKind() == ElementKind.FIELD) {
1039                            currentElementPtr[0] = el.getSimpleName().toString();
1040                        }
1041                    }
1042                }
1043            }, true);
1044        } catch (IOException JavaDoc ioex) {
1045            ErrorManager.getDefault().notify(ioex);
1046            return null;
1047        }
1048        return currentElementPtr[0];
1049    }
1050    
1051    private JEditorPane JavaDoc getCurrentEditor () {
1052        EditorCookie e = getCurrentEditorCookie ();
1053        if (e == null) return null;
1054        JEditorPane JavaDoc[] op = e.getOpenedPanes ();
1055        // We listen on open panes if e implements EditorCookie.Observable
1056
if ((op == null) || (op.length < 1)) return null;
1057        return op [0];
1058    }
1059    
1060    private EditorCookie getCurrentEditorCookie () {
1061        synchronized (currentLock) {
1062            if (currentEditorCookie == null) {
1063                TopComponent tc = TopComponent.getRegistry().getActivated();
1064                if (tc != null) {
1065                    currentEditorCookie = (EditorCookie) tc.getLookup().lookup(EditorCookie.class);
1066                }
1067                // Listen on open panes if currentEditorCookie implements EditorCookie.Observable
1068
if (currentEditorCookie instanceof EditorCookie.Observable) {
1069                    if (editorObservableListener == null) {
1070                        editorObservableListener = new EditorLookupListener(EditorCookie.Observable.class);
1071                    }
1072                    ((EditorCookie.Observable) currentEditorCookie).addPropertyChangeListener(editorObservableListener);
1073                }
1074            }
1075            return currentEditorCookie;
1076        }
1077    }
1078    
1079    private Line.Set getLineSet (String JavaDoc url, Object JavaDoc timeStamp) {
1080        DataObject dataObject = getDataObject (url);
1081        if (dataObject == null) return null;
1082        
1083        if (timeStamp != null) {
1084            // get original
1085
Registry registry = (Registry) timeStampToRegistry.get (timeStamp);
1086            if (registry != null) {
1087                Line.Set ls = registry.getLineSet (dataObject);
1088                if (ls != null) return ls;
1089            }
1090        }
1091        
1092        // get current
1093
LineCookie lineCookie = (LineCookie) dataObject.getCookie
1094            (LineCookie.class);
1095        if (lineCookie == null) return null;
1096        return lineCookie.getLineSet ();
1097    }
1098
1099    private Line getLine (String JavaDoc url, int lineNumber, Object JavaDoc timeStamp) {
1100        Line.Set ls = getLineSet (url, timeStamp);
1101        if (ls == null) return null;
1102        try {
1103            if (timeStamp == null)
1104                return ls.getCurrent (lineNumber - 1);
1105            else
1106                return ls.getOriginal (lineNumber - 1);
1107        } catch (IndexOutOfBoundsException JavaDoc e) {
1108        } catch (IllegalArgumentException JavaDoc e) {
1109        }
1110        return null;
1111    }
1112
1113    private static DataObject getDataObject (String JavaDoc url) {
1114        FileObject file;
1115        try {
1116            file = URLMapper.findFileObject (new URL JavaDoc (url));
1117        } catch (MalformedURLException JavaDoc e) {
1118            return null;
1119        }
1120
1121        if (file == null) return null;
1122        try {
1123            return DataObject.find (file);
1124        } catch (DataObjectNotFoundException ex) {
1125            return null;
1126        }
1127    }
1128    
1129    private static class Registry {
1130        
1131        private Map JavaDoc dataObjectToLineSet = new HashMap JavaDoc ();
1132        
1133        void register (DataObject dataObject) {
1134            LineCookie lc = (LineCookie) dataObject.getCookie (LineCookie.class);
1135            if (lc == null) return;
1136            dataObjectToLineSet.put (dataObject, lc.getLineSet ());
1137        }
1138        
1139        Line.Set getLineSet (DataObject dataObject) {
1140            return (Line.Set) dataObjectToLineSet.get (dataObject);
1141        }
1142    }
1143    
1144    private class ChangedFilesListener implements ChangeListener JavaDoc {
1145        public void stateChanged (ChangeEvent JavaDoc e) {
1146            Set JavaDoc newDOs = new HashSet JavaDoc (
1147                DataObject.getRegistry ().getModifiedSet ()
1148            );
1149            newDOs.removeAll (modifiedDataObjects);
1150            Iterator JavaDoc i1 = timeStampToRegistry.values ().iterator ();
1151            while (i1.hasNext ()) {
1152                Registry r = (Registry) i1.next ();
1153                Iterator JavaDoc i2 = newDOs.iterator ();
1154                while (i2.hasNext ())
1155                    r.register ((DataObject) i2.next ());
1156            }
1157            modifiedDataObjects = new HashSet JavaDoc (
1158                DataObject.getRegistry ().getModifiedSet ()
1159            );
1160        }
1161    }
1162    
1163    private class EditorLookupListener extends Object JavaDoc implements LookupListener, PropertyChangeListener JavaDoc {
1164        
1165        private Class JavaDoc type;
1166        
1167        public EditorLookupListener(Class JavaDoc type) {
1168            this.type = type;
1169        }
1170        
1171        public void resultChanged(LookupEvent ev) {
1172            if (type == DataObject.class) {
1173                synchronized (currentLock) {
1174                    currentURL = null;
1175                    //currentElement = null;
1176
if (currentEditorCookie instanceof EditorCookie.Observable) {
1177                        ((EditorCookie.Observable) currentEditorCookie).
1178                                removePropertyChangeListener(editorObservableListener);
1179                    }
1180                    currentEditorCookie = null;
1181                }
1182                pcs.firePropertyChange (TopComponent.Registry.PROP_CURRENT_NODES, null, null);
1183            } else if (type == EditorCookie.class) {
1184                synchronized (currentLock) {
1185                    currentURL = null;
1186                    //currentElement = null;
1187
if (currentEditorCookie instanceof EditorCookie.Observable) {
1188                        ((EditorCookie.Observable) currentEditorCookie).
1189                                removePropertyChangeListener(editorObservableListener);
1190                    }
1191                    currentEditorCookie = null;
1192                }
1193                pcs.firePropertyChange (TopComponent.Registry.PROP_CURRENT_NODES, null, null);
1194            } else if (type == Node.class) {
1195                synchronized (currentLock) {
1196                    //currentElement = null;
1197
}
1198                pcs.firePropertyChange (TopComponent.Registry.PROP_CURRENT_NODES, null, null);
1199            }
1200        }
1201        
1202        public void propertyChange(PropertyChangeEvent JavaDoc evt) {
1203            if (evt.getPropertyName().equals(EditorCookie.Observable.PROP_OPENED_PANES)) {
1204                pcs.firePropertyChange (EditorCookie.Observable.PROP_OPENED_PANES, null, null);
1205            }
1206        }
1207        
1208    }
1209    
1210    private static final class OperationHighlight implements Highlight {
1211    
1212        private Coloring coloring;
1213        private int start;
1214        private int end;
1215
1216        /** Creates a new instance of OperationHighlight */
1217        public OperationHighlight(Coloring coloring, int start, int end) {
1218            this.coloring = coloring;
1219            this.start = start;
1220            this.end = end;
1221        }
1222
1223        public int getStart() {
1224            return start;
1225        }
1226
1227        public int getEnd() {
1228            return end;
1229        }
1230
1231        public Coloring getColoring() {
1232            return coloring;
1233        }
1234
1235    }
1236    
1237    private class OperationCreationDelegateImpl implements AST2Bytecode.OperationCreationDelegate {
1238        /*
1239         public Operation createOperation(
1240                 Position startPosition,
1241                 Position endPosition,
1242                 int bytecodeIndex) {
1243             return EditorContextImpl.this.createOperation(
1244                     startPosition,
1245                     endPosition,
1246                     bytecodeIndex);
1247         }
1248         */

1249         public Operation createMethodOperation(
1250                 Position startPosition,
1251                 Position endPosition,
1252                 Position methodStartPosition,
1253                 Position methodEndPosition,
1254                 String JavaDoc methodName,
1255                 String JavaDoc methodClassType,
1256                 int bytecodeIndex) {
1257             return EditorContextImpl.this.createMethodOperation(
1258                     startPosition,
1259                     endPosition,
1260                     methodStartPosition,
1261                     methodEndPosition,
1262                     methodName,
1263                     methodClassType,
1264                     bytecodeIndex);
1265         }
1266         public Position createPosition(
1267                 int offset,
1268                 int line,
1269                 int column) {
1270             return EditorContextImpl.this.createPosition(
1271                     offset,
1272                     line,
1273                     column);
1274         }
1275         public void addNextOperationTo(Operation operation, Operation next) {
1276             EditorContextImpl.this.addNextOperationTo(operation, next);
1277         }
1278    }
1279    
1280}
1281
Popular Tags