001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.cnd.debugger.gdb;
043:
044: import java.beans.PropertyChangeListener;
045: import java.io.File;
046: import java.io.IOException;
047: import java.net.MalformedURLException;
048: import java.net.URL;
049: import java.util.List;
050: import java.util.logging.Logger;
051: import org.netbeans.api.debugger.DebuggerManager;
052: import org.netbeans.modules.cnd.debugger.gdb.breakpoints.AddressBreakpoint;
053: import org.netbeans.modules.cnd.debugger.gdb.breakpoints.FunctionBreakpoint;
054: import org.netbeans.modules.cnd.debugger.gdb.breakpoints.GdbBreakpoint;
055: import org.netbeans.modules.cnd.debugger.gdb.breakpoints.LineBreakpoint;
056: import org.netbeans.modules.cnd.debugger.gdb.disassembly.Disassembly;
057: import org.openide.filesystems.FileObject;
058: import org.openide.filesystems.FileStateInvalidException;
059: import org.openide.filesystems.FileUtil;
060: import org.openide.loaders.DataObject;
061: import org.openide.loaders.DataObjectNotFoundException;
062: import org.openide.util.Utilities;
063:
064: /*
065: *
066: * @author Jan Jancura and Gordon Prieur
067: */
068: public class EditorContextBridge {
069:
070: public static final String FUNCTION = "function"; // NOI18N
071: public static final String LINE = "line"; // NOI18N
072:
073: private static EditorContext context;
074: private static Logger log = Logger.getLogger("gdb.logger"); // NOI18N
075:
076: public static EditorContext getContext() {
077: if (context == null) {
078: List l = DebuggerManager.getDebuggerManager().lookup(null,
079: EditorContext.class);
080: context = (EditorContext) l.get(0);
081: int i, k = l.size();
082: for (i = 1; i < k; i++) {
083: context = new CompoundContextProvider((EditorContext) l
084: .get(i), context);
085: }
086: }
087: return context;
088: }
089:
090: public static boolean showSource(String url, int lineNumber,
091: Object timeStamp) {
092: return getContext().showSource(url, lineNumber, timeStamp);
093: }
094:
095: public static boolean showSource(CallStackFrame csf) {
096: if (Disassembly.isInDisasm()) {
097: return showDis(csf);
098: } else {
099: return showCode(csf);
100: }
101: }
102:
103: public static boolean showCode(CallStackFrame csf) {
104: String fullname = csf.getFullname();
105:
106: if (fullname != null) {
107: File file = new File(fullname);
108: if (file.exists()) {
109: FileObject fo = FileUtil.toFileObject(file);
110: if (fo != null) {
111: try {
112: return getContext().showSource(
113: DataObject.find(fo),
114: csf.getLineNumber(), null);
115: } catch (DataObjectNotFoundException dex) {
116: // do nothing
117: }
118: }
119: }
120: }
121: return false;
122: }
123:
124: public static boolean showDis(CallStackFrame csf) {
125: Disassembly dis = Disassembly.getCurrent();
126: if (dis == null) {
127: return false;
128: }
129: int line = dis.getAddressLine(csf.getAddr());
130: if (line != -1) {
131: FileObject fo = Disassembly.getFileObject();
132: if (fo != null) {
133: try {
134: return getContext().showSource(DataObject.find(fo),
135: line, null);
136: } catch (DataObjectNotFoundException dex) {
137: // do nothing
138: }
139: }
140: }
141: return false;
142: }
143:
144: public static String getUrl(File file) {
145: try {
146: file = file.getCanonicalFile();
147: } catch (IOException ioe) {
148: }
149: FileObject fo = FileUtil.toFileObject(file);
150: String url;
151: try {
152: url = fo.getURL().toExternalForm();
153: } catch (FileStateInvalidException ex) {
154: if (Utilities.isWindows()) {
155: url = "file:/" + fo.getPath().replace(" ", "%20"); // NOI18N
156: } else {
157: url = "file:/" + fo.getPath(); // NOI18N
158: }
159: }
160: return url;
161: }
162:
163: /**
164: * Creates a new time stamp.
165: *
166: * @param timeStamp a new time stamp
167: */
168: public static void createTimeStamp(Object timeStamp) {
169: getContext().createTimeStamp(timeStamp);
170: }
171:
172: /**
173: * Disposes given time stamp.
174: *
175: * @param timeStamp a time stamp to be disposed
176: */
177: public static void disposeTimeStamp(Object timeStamp) {
178: getContext().disposeTimeStamp(timeStamp);
179: }
180:
181: /**
182: * Adds annotation to given url on given line.
183: *
184: * @param url a url of source annotation should be set into
185: * @param lineNumber a number of line annotation should be set into
186: * @param annotationType a type of annotation to be set
187: *
188: * @return annotation
189: */
190: public static Object annotate(String url, int lineNumber,
191: String annotationType, Object timeStamp) {
192: return getContext().annotate(url, lineNumber, annotationType,
193: timeStamp);
194: }
195:
196: public static Object annotate(DataObject dobj, int lineNumber,
197: String annotationType, Object timeStamp) {
198: return getContext().annotate(dobj, lineNumber, annotationType,
199: timeStamp);
200: }
201:
202: /**
203: * Adds annotation to given url on given line.
204: *
205: * @param csf The current CallStackFrame
206: * @return annotation
207: */
208: public static Object annotate(CallStackFrame csf,
209: String annotationType) {
210: String fullname = csf.getFullname();
211: if (fullname != null) {
212: File file = new File(fullname);
213: if (file.exists()) {
214: FileObject fo = FileUtil.toFileObject(file);
215: if (fo != null) {
216: try {
217: return getContext().annotate(
218: DataObject.find(fo),
219: csf.getLineNumber(), annotationType,
220: null);
221: } catch (DataObjectNotFoundException dex) {
222: // do nothing
223: }
224: }
225: }
226: }
227: return null;
228: }
229:
230: public static Object annotateDis(CallStackFrame csf,
231: String annotationType) {
232: Disassembly dis = Disassembly.getCurrent();
233: if (dis == null) {
234: return null;
235: }
236: int line = dis.getAddressLine(csf.getAddr());
237: if (line != -1) {
238: FileObject fo = Disassembly.getFileObject();
239: if (fo != null) {
240: try {
241: return getContext().annotate(DataObject.find(fo),
242: line, annotationType, null);
243: } catch (DataObjectNotFoundException dex) {
244: // do nothing
245: }
246: }
247: }
248: return null;
249: }
250:
251: /**
252: * Removes given annotation.
253: */
254: public static void removeAnnotation(Object annotation) {
255: getContext().removeAnnotation(annotation);
256: }
257:
258: /**
259: * Returns line number given annotation is associated with.
260: *
261: * @return line number given annotation is associated with
262: */
263: public static int getLineNumber(Object annotation, Object timeStamp) {
264: return getContext().getLineNumber(annotation, timeStamp);
265: }
266:
267: /**
268: * Returns number of line currently selected in editor or <code>null</code>.
269: *
270: * @return number of line currently selected in editor or <code>0</code>
271: */
272: public static int getCurrentLineNumber() {
273: return getContext().getCurrentLineNumber();
274: }
275:
276: /**
277: * Returns number of line currently selected in editor or <code>null</code>.
278: *
279: * @return number of line currently selected in editor or <code>0</code>
280: */
281: public static int getMostRecentLineNumber() {
282: return getContext().getMostRecentLineNumber();
283: }
284:
285: /**
286: * Returns URL of source currently selected in editor or <code>null</code>.
287: *
288: * @return URL of source currently selected in editor or <code>null</code>
289: */
290: public static String getCurrentURL() {
291: return getContext().getCurrentURL();
292: }
293:
294: /**
295: * Return the most recent URL or empty string. The difference between this and getCurrentURL()
296: * is that this one will return a URL when the editor has lost focus.
297: *
298: * @return url in string form
299: */
300: public static String getMostRecentURL() {
301: return getContext().getMostRecentURL();
302: }
303:
304: /**
305: * Returns name of method currently selected in editor or <code>null</code>.
306: *
307: * @return name of method currently selected in editor or <code>null</code>
308: */
309: public static String getCurrentFunctionName() {
310: return getContext().getCurrentFunctionName();
311: }
312:
313: /**
314: * Returns method name currently selected in editor or <code>null</code>.
315: *
316: * @return method name currently selected in editor or <code>null</code>
317: */
318: public static String getSelectedFunctionName() {
319: return getContext().getSelectedFunctionName();
320: }
321:
322: /**
323: * Returns line number of given field in given class.
324: *
325: * @param url the url of file the class is deined in
326: * @param className the name of class (or innerclass) the field is
327: * defined in
328: * @param fieldName the name of field
329: *
330: * @return line number or -1
331: */
332: public static int getFieldLineNumber(String url, String className,
333: String fieldName) {
334: return getContext().getFieldLineNumber(url, className,
335: fieldName);
336: }
337:
338: /**
339: * Get the MIME type of the current file.
340: *
341: * @return The MIME type of the current file
342: */
343: public String getCurrentMIMEType() {
344: return getContext().getCurrentMIMEType();
345: }
346:
347: /**
348: * Get the MIME type of the most recently selected file.
349: *
350: * @return The MIME type of the most recent selected file
351: */
352: public static String getMostRecentMIMEType() {
353: return getContext().getMostRecentMIMEType();
354: }
355:
356: /**
357: * Adds a property change listener.
358: *
359: * @param l the listener to add
360: */
361: public void addPropertyChangeListener(PropertyChangeListener l) {
362: getContext().addPropertyChangeListener(l);
363: }
364:
365: public static void removePropertyChangeListener(
366: PropertyChangeListener l) {
367: getContext().removePropertyChangeListener(l);
368: }
369:
370: // utility methods .........................................................
371:
372: public static String getFileName(GdbBreakpoint b) {
373: try {
374: return basename(new File(new URL(b.getURL()).getFile())
375: .getName());
376: } catch (MalformedURLException e) {
377: return null;
378: }
379: }
380:
381: private static String basename(String name) {
382: int idx = name.lastIndexOf('/');
383:
384: if (idx > 0) {
385: return name.substring(idx);
386: } else {
387: return name;
388: }
389: }
390:
391: public static boolean showSource(GdbBreakpoint b, Object timeStamp) {
392: if (b instanceof LineBreakpoint) {
393: if (b.getLineNumber() < 1) {
394: return EditorContextBridge.showSource(b.getURL(), 1,
395: timeStamp);
396: }
397: return EditorContextBridge.showSource(b.getURL(), b
398: .getLineNumber(), timeStamp);
399: } else if (b instanceof AddressBreakpoint) {
400: FileObject fo = Disassembly.getFileObject();
401: if (fo != null) {
402: try {
403: Disassembly dis = Disassembly.getCurrent();
404: if (dis != null) {
405: int line = dis
406: .getAddressLine(((AddressBreakpoint) b)
407: .getAddress());
408: if (line != -1) {
409: return getContext()
410: .showSource(
411: DataObject.find(fo),
412: dis
413: .getAddressLine(((AddressBreakpoint) b)
414: .getAddress()),
415: null);
416: } else {
417: Disassembly.open();
418: }
419: }
420: } catch (DataObjectNotFoundException dex) {
421: // do nothing
422: }
423: }
424: }
425: return false;
426: }
427:
428: public static String getDefaultType() {
429: return LINE;
430: }
431:
432: public static Object annotate(GdbBreakpoint b) {
433: String url = b.getURL();
434: int lineNumber = b.getLineNumber();
435: if (lineNumber < 1) {
436: return null;
437: }
438: String condition = b.getCondition();
439: boolean isConditional = condition.trim().length() > 0;
440: String annotationType;
441: if (b instanceof FunctionBreakpoint) {
442: if (b.isEnabled()) {
443: annotationType = isConditional ? EditorContext.CONDITIONAL_FUNCTION_BREAKPOINT_ANNOTATION_TYPE
444: : EditorContext.FUNCTION_BREAKPOINT_ANNOTATION_TYPE;
445: } else {
446: annotationType = isConditional ? EditorContext.DISABLED_CONDITIONAL_FUNCTION_BREAKPOINT_ANNOTATION_TYPE
447: : EditorContext.DISABLED_FUNCTION_BREAKPOINT_ANNOTATION_TYPE;
448: }
449: } else if (b instanceof AddressBreakpoint) {
450: Disassembly dis = Disassembly.getCurrent();
451: if (dis == null) {
452: return null;
453: }
454: lineNumber = dis.getAddressLine(((AddressBreakpoint) b)
455: .getAddress());
456: if (lineNumber == -1) {
457: return null;
458: }
459: if (b.isEnabled()) {
460: annotationType = isConditional ? EditorContext.CONDITIONAL_ADDRESS_BREAKPOINT_ANNOTATION_TYPE
461: : EditorContext.ADDRESS_BREAKPOINT_ANNOTATION_TYPE;
462: } else {
463: annotationType = isConditional ? EditorContext.DISABLED_CONDITIONAL_ADDRESS_BREAKPOINT_ANNOTATION_TYPE
464: : EditorContext.DISABLED_ADDRESS_BREAKPOINT_ANNOTATION_TYPE;
465: }
466: try {
467: return annotate(DataObject.find(Disassembly
468: .getFileObject()), lineNumber, annotationType,
469: null);
470: } catch (DataObjectNotFoundException doe) {
471: doe.printStackTrace();
472: return null;
473: }
474: } else {
475: if (b.isEnabled()) {
476: annotationType = isConditional ? EditorContext.CONDITIONAL_BREAKPOINT_ANNOTATION_TYPE
477: : EditorContext.BREAKPOINT_ANNOTATION_TYPE;
478: } else {
479: annotationType = isConditional ? EditorContext.DISABLED_CONDITIONAL_BREAKPOINT_ANNOTATION_TYPE
480: : EditorContext.DISABLED_BREAKPOINT_ANNOTATION_TYPE;
481: }
482: }
483:
484: return annotate(url, lineNumber, annotationType, null);
485: }
486:
487: public static String getRelativePath(String className) {
488: String sourceName = className.replace('.', '/') + ".java"; // NOI18N
489: return sourceName;
490: }
491:
492: private static String convertSlash(String original) {
493: return original.replace(File.separatorChar, '/');
494: }
495:
496: private static class CompoundContextProvider extends EditorContext {
497:
498: private EditorContext cp1, cp2;
499:
500: CompoundContextProvider(EditorContext cp1, EditorContext cp2) {
501: this .cp1 = cp1;
502: this .cp2 = cp2;
503: }
504:
505: public void createTimeStamp(Object timeStamp) {
506: cp1.createTimeStamp(timeStamp);
507: cp2.createTimeStamp(timeStamp);
508: }
509:
510: public void disposeTimeStamp(Object timeStamp) {
511: cp1.disposeTimeStamp(timeStamp);
512: cp2.disposeTimeStamp(timeStamp);
513: }
514:
515: public void updateTimeStamp(Object timeStamp, String url) {
516: cp1.updateTimeStamp(timeStamp, url);
517: cp2.updateTimeStamp(timeStamp, url);
518: }
519:
520: public String getCurrentURL() {
521: String s = cp1.getCurrentURL();
522: if (s.trim().length() < 1) {
523: return cp2.getCurrentURL();
524: }
525: return s;
526: }
527:
528: public String getMostRecentURL() {
529: String s = cp1.getMostRecentURL();
530: if (s.trim().length() < 1) {
531: return cp2.getMostRecentURL();
532: }
533: return s;
534: }
535:
536: public int getCurrentLineNumber() {
537: int i = cp1.getCurrentLineNumber();
538: if (i < 1) {
539: return cp2.getCurrentLineNumber();
540: }
541: return i;
542: }
543:
544: public int getMostRecentLineNumber() {
545: int i = cp1.getMostRecentLineNumber();
546: if (i < 1) {
547: return cp2.getMostRecentLineNumber();
548: }
549: return i;
550: }
551:
552: public String getCurrentFunctionName() {
553: String s = cp1.getCurrentFunctionName();
554: if ((s == null) || (s.trim().length() < 1)) {
555: return cp2.getCurrentFunctionName();
556: }
557: return s;
558: }
559:
560: public DataObject getCurrentDataObject() {
561: DataObject dobj = cp1.getCurrentDataObject();
562: if (dobj == null) {
563: dobj = cp2.getCurrentDataObject();
564: }
565: return dobj;
566: }
567:
568: public String getSelectedFunctionName() {
569: String s = cp1.getSelectedFunctionName();
570: if ((s == null) || (s.trim().length() < 1)) {
571: return cp2.getSelectedFunctionName();
572: }
573: return s;
574: }
575:
576: public void removeAnnotation(Object annotation) {
577: CompoundAnnotation ca = (CompoundAnnotation) annotation;
578: cp1.removeAnnotation(ca.annotation1);
579: cp2.removeAnnotation(ca.annotation2);
580: }
581:
582: public Object annotate(String sourceName, int lineNumber,
583: String annotationType, Object timeStamp) {
584: CompoundAnnotation ca = new CompoundAnnotation();
585: ca.annotation1 = cp1.annotate(sourceName, lineNumber,
586: annotationType, timeStamp);
587: ca.annotation2 = cp2.annotate(sourceName, lineNumber,
588: annotationType, timeStamp);
589: return ca;
590: }
591:
592: public Object annotate(DataObject dobj, int lineNumber,
593: String annotationType, Object timeStamp) {
594: CompoundAnnotation ca = new CompoundAnnotation();
595: ca.annotation1 = cp1.annotate(dobj, lineNumber,
596: annotationType, timeStamp);
597: ca.annotation2 = cp2.annotate(dobj, lineNumber,
598: annotationType, timeStamp);
599: return ca;
600: }
601:
602: public int getLineNumber(Object annotation, Object timeStamp) {
603: CompoundAnnotation ca = new CompoundAnnotation();
604: int ln = cp1.getLineNumber(ca.annotation1, timeStamp);
605: if (ln >= 0) {
606: return ln;
607: }
608: return cp2.getLineNumber(ca.annotation2, timeStamp);
609: }
610:
611: public boolean showSource(String sourceName, int lineNumber,
612: Object timeStamp) {
613: return cp1.showSource(sourceName, lineNumber, timeStamp)
614: | cp2.showSource(sourceName, lineNumber, timeStamp);
615: }
616:
617: public boolean showSource(DataObject dobj, int lineNumber,
618: Object timeStamp) {
619: return cp1.showSource(dobj, lineNumber, timeStamp)
620: | cp2.showSource(dobj, lineNumber, timeStamp);
621: }
622:
623: public int getFieldLineNumber(String url, String className,
624: String fieldName) {
625: int ln = cp1.getFieldLineNumber(url, className, fieldName);
626: if (ln != -1) {
627: return ln;
628: }
629: return cp2.getFieldLineNumber(url, className, fieldName);
630: }
631:
632: public String getCurrentMIMEType() {
633: String s = cp1.getCurrentMIMEType();
634: if (s == null) {
635: return cp2.getCurrentMIMEType();
636: }
637: return s;
638: }
639:
640: public String getMostRecentMIMEType() {
641: String s = cp1.getMostRecentMIMEType();
642: if (s == null) {
643: return cp2.getMostRecentMIMEType();
644: }
645: return s;
646: }
647:
648: public void addPropertyChangeListener(PropertyChangeListener l) {
649: cp1.addPropertyChangeListener(l);
650: cp2.addPropertyChangeListener(l);
651: }
652:
653: public void removePropertyChangeListener(
654: PropertyChangeListener l) {
655: cp1.removePropertyChangeListener(l);
656: cp2.removePropertyChangeListener(l);
657: }
658:
659: public void addPropertyChangeListener(String propertyName,
660: PropertyChangeListener l) {
661: cp1.addPropertyChangeListener(propertyName, l);
662: cp2.addPropertyChangeListener(propertyName, l);
663: }
664:
665: public void removePropertyChangeListener(String propertyName,
666: PropertyChangeListener l) {
667: cp1.removePropertyChangeListener(propertyName, l);
668: cp2.removePropertyChangeListener(propertyName, l);
669: }
670: }
671:
672: private static class CompoundAnnotation {
673: public CompoundAnnotation() {
674: }
675:
676: Object annotation1;
677: Object annotation2;
678: }
679:
680: }
|