alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 * 
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 * 
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2004 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.modules.debugger.projects;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import javax.swing.JEditorPane;

import org.netbeans.spi.debugger.jpda.EditorContext;

import org.openide.cookies.EditorCookie;
import org.openide.cookies.LineCookie;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.loaders.DataNode;
import org.openide.loaders.DataObject;
import org.openide.loaders.DataShadow;
import org.openide.loaders.DataObjectNotFoundException;
import org.openide.nodes.Node;
import org.openide.src.ClassElement;
import org.openide.src.ConstructorElement;
import org.openide.src.Element;
import org.openide.src.FieldElement;
import org.openide.src.Identifier;
import org.openide.src.InitializerElement;
import org.openide.src.SourceElement;
import org.openide.text.Line;
import org.openide.text.NbDocument;
import org.openide.util.Utilities;
import org.openide.windows.TopComponent;

import java.net.URL;
import java.net.MalformedURLException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.Document;
import javax.swing.text.StyledDocument;
import org.netbeans.api.debugger.jpda.LineBreakpoint;
import org.openide.cookies.SourceCookie;
import org.openide.filesystems.FileChangeListener;
import org.openide.filesystems.FileEvent;
import org.openide.filesystems.FileStateInvalidException;
import org.openide.filesystems.URLMapper;
import org.openide.src.Import;

/**
 *
 * @author Jan Jancura
 */
public class EditorContextImpl extends EditorContext implements 
PropertyChangeListener {
    
    private PropertyChangeSupport   pcs;
    private Map                     annotationToURL = new HashMap ();
    private ChangeListener          changedFilesListener;
    private Map                     timeStampToRegistry = new HashMap ();
    private Set                     modifiedDataObjects;
    
    
    {
        pcs = new PropertyChangeSupport (this);
        TopComponent.getRegistry ().addPropertyChangeListener (this);
    }
    
    
    /**
     * Shows source with given url on given line number.
     *
     * @param url a url of source to be shown
     * @param lineNumber a number of line to be shown
     * @param timeStamp a time stamp to be used
     */
    public boolean showSource (String url, int lineNumber, Object timeStamp) {
        Line l = getLine (url, lineNumber, timeStamp); // false = use original ln
        if (l == null) return false;
        l.show (Line.SHOW_GOTO);
        return true;
    }

    /**
     * Creates a new time stamp.
     *
     * @param timeStamp a new time stamp
     */
    public void createTimeStamp (Object timeStamp) {
        modifiedDataObjects = new HashSet (
            DataObject.getRegistry ().getModifiedSet ()
        );
        Registry r = new Registry ();
        timeStampToRegistry.put (timeStamp, r);
        Iterator i = modifiedDataObjects.iterator ();
        while (i.hasNext ())
            r.register ((DataObject) i.next ());
        if (changedFilesListener == null) {
            changedFilesListener = new ChangedFilesListener ();
            DataObject.getRegistry ().addChangeListener (changedFilesListener);
        }
    }

    /**
     * Disposes given time stamp.
     *
     * @param timeStamp a time stamp to be disposed
     */
    public void disposeTimeStamp (Object timeStamp) {
        timeStampToRegistry.remove (timeStamp);
        if (timeStampToRegistry.isEmpty ()) {
            DataObject.getRegistry ().removeChangeListener (changedFilesListener);
            changedFilesListener = null;
        }
    }
    
    /**
     * Adds annotation to given url on given line.
     *
     * @param url a url of source annotation should be set into
     * @param lineNumber a number of line annotation should be set into
     * @param annotationType a type of annotation to be set
     *
     * @return annotation
     */
    public Object annotate (
        String url, 
        int lineNumber, 
        String annotationType,
        Object timeStamp
    ) {
        Line l =  getLine (
            url, 
            lineNumber, 
            timeStamp
        );
        if (l == null) return null;
        DebuggerAnnotation annotation =
            new DebuggerAnnotation (annotationType, l);
        annotationToURL.put (annotation, url);
        
        return annotation;
    }

    /**
     * Removes given annotation.
     *
     * @return true if annotation has been successfully removed
     */
    public void removeAnnotation (
        Object a
    ) {
        DebuggerAnnotation annotation = (DebuggerAnnotation) a;
        annotation.detach ();
        
        if (annotationToURL.remove (annotation) == null) {
            Thread.dumpStack();
            return;
        }
    }

    /**
     * Returns line number given annotation is associated with.
     *
     * @param annotation a annotation
     * @param timeStamp a time stamp to be used
     *
     * @return line number given annotation is associated with
     */
    public int getLineNumber (
        Object a,
        Object timeStamp
    ) {
        DebuggerAnnotation annotation = (DebuggerAnnotation) a;
        if (timeStamp == null) 
            return annotation.getLine ().getLineNumber () + 1;
        String url = (String) annotationToURL.get (annotation);
        Line.Set lineSet = getLineSet (url, timeStamp);
        return lineSet.getOriginalLineNumber (annotation.getLine ()) + 1;
    }

    /**
     * Returns number of line currently selected in editor or -1.
     *
     * @return number of line currently selected in editor or -1
     */
    public int getCurrentLineNumber () {
        EditorCookie e = getCurrentEditorCookie ();
        if (e == null) return -1;
        JEditorPane ep = getCurrentEditor ();
        if (ep == null) return -1;
        StyledDocument d = e.getDocument ();
        if (d == null) return -1;
        int ln = NbDocument.findLineNumber (
            d,
            ep.getCaret ().getDot ()
        );
        return ln + 1;
    }
    
    /**
     * Returns name of class currently selected in editor or empty string.
     *
     * @return name of class currently selected in editor or empty string
     */
    public String getCurrentClassName () {
        Element e = getCurrentElement ();
        if (e == null) return "";
        if (e instanceof ClassElement)
            return getClassName ((ClassElement) e);
        if (e instanceof ConstructorElement)
            return getClassName (((ConstructorElement) e).getDeclaringClass ());
        if (e instanceof FieldElement)
            return getClassName (((FieldElement) e).getDeclaringClass ());
        if (e instanceof InitializerElement)
            return getClassName (((InitializerElement) e).getDeclaringClass());
        return "";
    }

    /**
     * Returns URL of source currently selected in editor or empty string.
     *
     * @return URL of source currently selected in editor or empty string
     */
    public String getCurrentURL () {
        Node[] nodes = TopComponent.getRegistry ().getCurrentNodes ();
        if (nodes == null) return "";
        if (nodes.length != 1) return "";
        Node n = nodes [0];
        DataObject dO = null;
        if (n instanceof DataNode)
            dO = ((DataNode) n).getDataObject ();
        if (dO == null)
            dO = (DataObject) n.getCookie (DataObject.class);
        if (dO == null) return "";
        if (dO instanceof DataShadow)
            dO = ((DataShadow) dO).getOriginal ();
        
        try {
            return dO.getPrimaryFile ().getURL ().toString ();
        } catch (FileStateInvalidException ex) {
            return "";
        }
    }

    /**
     * Returns name of method currently selected in editor or empty string.
     *
     * @return name of method currently selected in editor or empty string
     */
    public String getCurrentMethodName () {
        Element e = getCurrentElement ();
        if (e instanceof ConstructorElement)
            return ((ConstructorElement) e).getName ().getName ();
        if (e instanceof InitializerElement)
            return ((InitializerElement) e).isStatic () ?
                "" : "";
        return "";
    }

    /**
     * Returns name of field currently selected in editor or null.
     *
     * @return name of field currently selected in editor or null
     */
    public String getCurrentFieldName () {
        Element e = getCurrentElement ();
        if (e instanceof FieldElement)
            return ((FieldElement) e).getName ().getName ();
        return getSelectedIdentifier ();
    }

    /**
     * Returns identifier currently selected in editor or null.
     *
     * @return identifier currently selected in editor or null
     */
    public String getSelectedIdentifier () {
        JEditorPane ep = getCurrentEditor ();
        if (ep == null) return null;
        String s = ep.getSelectedText ();
        if (s == null) return null;
        if (Utilities.isJavaIdentifier (s)) return s;
        return null;
    }

    /**
     * Returns method name currently selected in editor or empty string.
     *
     * @return method name currently selected in editor or empty string
     */
    public String getSelectedMethodName () {
        EditorCookie e = getCurrentEditorCookie ();
        if (e == null) return "";
        JEditorPane ep = getCurrentEditor ();
        if (ep == null) return "";
        StyledDocument doc = e.getDocument ();
        if (doc == null) return "";
        int offset = ep.getCaret ().getDot ();
        String t = null;
//        if ( (ep.getSelectionStart () <= offset) &&
//             (offset <= ep.getSelectionEnd ())
//        )   t = ep.getSelectedText ();
//        if (t != null) return t;
        
        int line = NbDocument.findLineNumber (
            doc,
            offset
        );
        int col = NbDocument.findLineColumn (
            doc,
            offset
        );
        try {
            javax.swing.text.Element lineElem = 
                org.openide.text.NbDocument.findLineRootElement (doc).
                getElement (line);

            if (lineElem == null) return "";
            int lineStartOffset = lineElem.getStartOffset ();
            int lineLen = lineElem.getEndOffset () - lineStartOffset;
            // t contains current line in editor
            t = doc.getText (lineStartOffset, lineLen);
            
            int identStart = col;
            while ( identStart > 0 && 
                    Character.isJavaIdentifierPart (
                        t.charAt (identStart - 1)
                    )
            )   identStart--;

            int identEnd = col;
            while (identEnd < lineLen && 
                   Character.isJavaIdentifierPart (t.charAt (identEnd))
            ) {
                identEnd++;
            }
            int i = t.indexOf ('(', identEnd);
            if (i < 0) return "";
            if (t.substring (identEnd, i).trim ().length () > 0) return "";

            if (identStart == identEnd) return "";
            return t.substring (identStart, identEnd);
        } catch (javax.swing.text.BadLocationException ex) {
            return "";
        }
    }
    
    /**
     * Returns line number of given field in given class.
     *
     * @param url the url of file the class is deined in
     * @param className the name of class (or innerclass) the field is 
     *                  defined in
     * @param fieldName the name of field
     *
     * @return line number or -1
     */
    public int getFieldLineNumber (
        String url, 
        String className, 
        String fieldName
    ) {
        DataObject dataObject = getDataObject (url);
        if (dataObject == null) return -1;
        SourceCookie.Editor sc = (SourceCookie.Editor) dataObject.getCookie 
            (SourceCookie.Editor.class);
        if (sc == null) return -1;
        sc.open ();
        StyledDocument sd = sc.getDocument ();
        if (sd == null) return -1;
        ClassElement[] classes = sc.getSource ().getAllClasses ();
        FieldElement fe = null;
        int i, k = classes.length;
        for (i = 0; i < k; i++)
            if (classes [i].getName ().getFullName ().equals (className)) {
                fe = classes [i].getField (Identifier.create (fieldName));
                break;
            }
        if (fe == null) return -1;
        int position = sc.sourceToText (fe).getStartOffset ();
        return NbDocument.findLineNumber (sd, position) + 1;
    }

    /**
     * Returns list of imports for given source url.
     *
     * @param url the url of source file
     *
     * @return list of imports for given source url
     */
    public String[] getImports (
        String url
    ) {
        DataObject dataObject = getDataObject (url);
        if (dataObject == null) return new String [0];
        SourceCookie.Editor sc = (SourceCookie.Editor) dataObject.getCookie 
            (SourceCookie.Editor.class);
        if (sc == null) return new String [0];
        Import[] is = sc.getSource ().getImports ();
        int i, k = is.length;
        String[] is2 = new String [k];
        for (i = 0; i < k; i++)
            is2 [i] = is [i].getIdentifier ().getFullName ();
        return is2;
    }
    
    /**
     * Adds a property change listener.
     *
     * @param l the listener to add
     */
    public void addPropertyChangeListener (PropertyChangeListener l) {
        pcs.addPropertyChangeListener (l);
    }
    
    /**
     * Removes a property change listener.
     *
     * @param l the listener to remove
     */
    public void removePropertyChangeListener (PropertyChangeListener l) {
        pcs.removePropertyChangeListener (l);
    }
    
    /**
     * Adds a property change listener.
     *
     * @param propertyName the name of property
     * @param l the listener to add
     */
    public void addPropertyChangeListener (
        String propertyName,
        PropertyChangeListener l
    ) {
        pcs.addPropertyChangeListener (propertyName, l);
    }
    
    /**
     * Removes a property change listener.
     *
     * @param propertyName the name of property
     * @param l the listener to remove
     */
    public void removePropertyChangeListener (
        String propertyName,
        PropertyChangeListener l
    ) {
        pcs.removePropertyChangeListener (propertyName, l);
    }

    
    // private helper methods ..................................................
    
    public void propertyChange (PropertyChangeEvent evt) {
	pcs.firePropertyChange (null, null, null);
    }
    
//    public void fileChanged (FileEvent fe) {
//	pcs.firePropertyChange (PROP_LINE_NUMBER, null, null);
//    }
//    
//    public void fileDeleted (FileEvent fe) {}
//    public void fileAttributeChanged (org.openide.filesystems.FileAttributeEvent fe) {}
//    public void fileDataCreated (FileEvent fe) {}
//    public void fileFolderCreated (FileEvent fe) {}
//    public void fileRenamed (org.openide.filesystems.FileRenameEvent fe) {}
    
    
    private static Element getCurrentElement () {
        Node[] nodes = TopComponent.getRegistry ().getCurrentNodes ();
        if (nodes == null) return null;
        if (nodes.length != 1) return null;
        Node n = nodes [0];
        return (Element) n.getCookie (Element.class);
    }
    
    private static JEditorPane getCurrentEditor () {
        EditorCookie e = getCurrentEditorCookie ();
        if (e == null) return null;
        JEditorPane[] op = e.getOpenedPanes ();
        if ((op == null) || (op.length < 1)) return null;
        return op [0];
    }
    
    private static EditorCookie getCurrentEditorCookie () {
        Node[] nodes = TopComponent.getRegistry ().getCurrentNodes ();
        if (nodes == null) return null;
        if (nodes.length != 1) return null;
        Node n = nodes [0];
        return (EditorCookie) n.getCookie (EditorCookie.class);
    }
    
    private static LineCookie getCurrentLineCookie () {
        Node[] nodes = TopComponent.getRegistry ().getCurrentNodes ();
        if (nodes == null) return null;
        if (nodes.length != 1) return null;
        Node n = nodes [0];
        return (LineCookie) n.getCookie (LineCookie.class);
    }
    
    private static String getClassName (ClassElement e) {
        String f = e.getName ().getFullName ();
        if (!e.isInner ()) return f;
        SourceElement sourceEl = e.getSource ();
        if (sourceEl == null) return f;            
        Identifier ident = sourceEl.getPackage ();
        String c;
        if (ident == null) c = ""; // NOI18N
        else c = ident.getFullName ();
        if (c.length () > 0)
            return c + '.' + f.substring (c.length () + 1).replace ('.', '$');
        return f.replace ('.', '$');
    }

    private Line.Set getLineSet (String url, Object timeStamp) {
        DataObject dataObject = getDataObject (url);
        if (dataObject == null) return null;
        
        if (timeStamp != null) {
            // get original
            Registry registry = (Registry) timeStampToRegistry.get (timeStamp);
            Line.Set ls = registry.getLineSet (dataObject);
            if (ls != null) return ls;
        }
        
        // get current
        LineCookie lineCookie = (LineCookie) dataObject.getCookie
            (LineCookie.class);
        if (lineCookie == null) return null;
        return lineCookie.getLineSet ();
    }

    private Line getLine (String url, int lineNumber, Object timeStamp) {
        Line.Set ls = getLineSet (url, timeStamp);
        if (ls == null) return null;
        try {
            if (timeStamp == null)
                return ls.getCurrent (lineNumber - 1);
            else
                return ls.getOriginal (lineNumber - 1);
        } catch (IndexOutOfBoundsException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        }
        return null;
    }

    private DataObject getDataObject (String url) {
        FileObject file;
        try {
            file = URLMapper.findFileObject (new URL (url));
        } catch (MalformedURLException e) {
            return null;
        }

        if (file == null) return null;
        DataObject dataObject = null;
        try {
            return DataObject.find (file);
        } catch (DataObjectNotFoundException ex) {
            return null;
        }
    }
    
    static class Registry {
        
        private Map dataObjectToLineSet = new HashMap ();
        
        void register (DataObject dataObject) {
            LineCookie lc = (LineCookie) dataObject.getCookie (LineCookie.class);
            if (lc == null) return;
            dataObjectToLineSet.put (dataObject, lc.getLineSet ());
        }
        
        Line.Set getLineSet (DataObject dataObject) {
            return (Line.Set) dataObjectToLineSet.get (dataObject);
        }
    }
    
    class ChangedFilesListener implements ChangeListener {
        public void stateChanged (ChangeEvent e) {
            Set newDOs = new HashSet (
                DataObject.getRegistry ().getModifiedSet ()
            );
            newDOs.removeAll (modifiedDataObjects);
            Iterator i1 = timeStampToRegistry.values ().iterator ();
            while (i1.hasNext ()) {
                Registry r = (Registry) i1.next ();
                Iterator i2 = newDOs.iterator ();
                while (i2.hasNext ())
                    r.register ((DataObject) i2.next ());
            }
            modifiedDataObjects = new HashSet (
                DataObject.getRegistry ().getModifiedSet ()
            );
        }
    }
}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.