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-2003 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.modules.tasklist.compiler;

import java.awt.Component;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.MessageFormat;
import java.util.Iterator;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.*;
import javax.swing.Action;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import org.netbeans.api.registry.Context;
import org.netbeans.api.registry.ContextException;
import org.netbeans.modules.tasklist.compiler.engine.CompilationEngineListener;
import org.netbeans.modules.tasklist.compiler.engine.MyCompilerTask;
import org.netbeans.modules.tasklist.compiler.tasktreetable.ErrorsTreeTable;
import org.netbeans.modules.tasklist.compiler.tasktreetable.SeverityTableCellRenderer;
import org.netbeans.modules.tasklist.compiler.treetable.ChooseColumnsPanel;
import org.netbeans.modules.tasklist.core.*;
import org.netbeans.modules.tasklist.core.columns.ColumnsConfiguration;
import org.netbeans.modules.tasklist.core.editors.StringPropertyEditor;
import org.netbeans.modules.tasklist.core.filter.Filter;
import org.netbeans.modules.tasklist.core.filter.FilterAction;
import org.netbeans.modules.tasklist.core.filter.RemoveFilterAction;
import org.netbeans.modules.tasklist.compiler.nodestreetable.NodesTreeTable;
import org.netbeans.modules.tasklist.compiler.nodestreetable.NodesTreeTableModel;
import org.openide.DialogDisplayer;
import org.openide.ErrorManager;
import org.openide.NotifyDescriptor;
import org.openide.awt.MouseUtils;
import org.openide.awt.StatusDisplayer;
import org.openide.compiler.CompilerTask;
import org.openide.compiler.ErrorEvent;
import org.openide.compiler.ProgressEvent;
import org.openide.explorer.ExplorerManager;
import org.openide.filesystems.FileObject;
import org.openide.nodes.Node;
import org.openide.text.Line;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.util.Utilities;
import org.openide.util.actions.SystemAction;

/**
 * View for compile errors.
 *
 * @author Tim Lebedkov
 */
public class CompileErrorsView extends TaskListView implements CompilationEngineListener {

    private static final long serialVersionUID = 1;

    private static final Logger LOGGER = TLUtils.getLogger(
        CompileErrorsView.class);
    
    static {
        LOGGER.setLevel(Level.OFF);
    }
    
    /**
     * Returns default "Build Errors" view
     *
     * @return the only instance of this class
     */
    public static CompileErrorsView getDefault() {
        CompileErrorsView def = 
            (CompileErrorsView) getTaskListView("compiler"); // NOI18N
        if (def == null)
            def = new CompileErrorsView();
        return def;
    }

    /**
     * Checks whether the view is already created
     *
     * @return true = the view is created
     */
    public static boolean isViewCreated() {
        return getTaskListView("compiler") != null; // NOI18N
    }

    private ResourceBundle rb;

    /** format for errors */
    private MessageFormat errorMsg;

    /** format for error description */
    private MessageFormat errorDescr;

    /** message for compiling */
    private MessageFormat compilingMsg;

    /** compilaton successful */
    private MessageFormat compSuccess;

    /** compilaton unsuccessful */
    private MessageFormat compUnsuccess;

    /** compilation started */
    private MessageFormat compStarted;

    /** compiling progress status messages */
    private String parsing;
    private String generating;
    private String writing;
    private String cleaning;

    private boolean initialized;
    private int nerr, nwarn, ninfo;
    private java.util.regex.Pattern javacInfos;

    /**
     * Will be set to true if the status line text was changed
     */
    private boolean statusTextSet = false;

    private CompileErrorsSettings settings;

    private BuildProcess defBuildProcess;
    
    /**
     * Creates a new instance of CompilerTaskView
     */
    private CompileErrorsView() {
        super("compiler", NbBundle.getMessage( // NOI18N
            CompileErrorsView.class, "TITLE_BuildErrors"), // NOI18N
            Utilities.loadImage("org/netbeans/modules/tasklist/compiler/viewerrors.png"),  // NOI18N
            true, new TaskList()); // TODO i18n

        rb = NbBundle.getBundle(CompileErrorsView.class);
        parsing = rb.getString("MSG_StatusParsing"); // NOI18N
        writing = rb.getString("MSG_StatusWriting"); // NOI18N
        generating = rb.getString("MSG_StatusGenerating"); // NOI18N
        cleaning = rb.getString("MSG_StatusCleaning"); // NOI18N
        errorMsg = new MessageFormat(rb.getString("MSG_CompileError")); // NOI18N
        errorDescr = new MessageFormat(rb.getString("MSG_CompileErrorDescr")); // NOI18N
        compilingMsg = new MessageFormat(rb.getString("MSG_Compiling")); // NOI18N
        compSuccess = new MessageFormat(rb.getString("MSG_CompilationSuccessful")); // NOI18N
        compUnsuccess = new MessageFormat(rb.getString("MSG_CompilationUnsuccessful")); // NOI18N
        compStarted = new MessageFormat(rb.getString("MSG_CompilationStarted")); // NOI18N

        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                setToolTipText(rb.getString("BuildErrorsViewDesc")); // NOI18N
            }
        });

        javacInfos = Pattern.compile(
            "([0-9]+ error(s)?)?( )*([0-9]+ warning(s)?)?"); // NOI18N
        try {
            String ctxName = "/Settings/org/netbeans/modules/tasklist/compiler"; // NOI18N
            Context ctx = Context.getDefault().createSubcontext(ctxName);
            settings = (CompileErrorsSettings)
                ctx.getObject("Settings", new CompileErrorsSettings()); // NOI18N
        } catch (ContextException e) {
            ErrorManager.getDefault().notify(e);
        }
    }

    public void showTaskInEditor(Task item, TaskAnnotation annotation) {
	hideTaskInEditor();
	if (item == null) {
	    return;
	}

        if (annotation == null)
            annotation = getAnnotation(item);
        
        StatusDisplayer.getDefault().setStatusText(item.getSummary());
        final Line.Part part = ((CompileError) item).getLinePart();
        final Line line = item.getLine();
        if (part != null && line != null) {
            annotation.attach(line);
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    line.show(Line.SHOW_GOTO, part.getColumn());
                }
            });
            taskMarker = annotation;
        } else if (line != null) {
            annotation.attach(line);
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    line.show(Line.SHOW_GOTO);
                }
            });
            taskMarker = annotation;
        }
    }
    
    /**
     * Makes the process build node sticky
     */
    public void clearDefaultBuildProcess() {
        defBuildProcess = null;
    }
    
    public SystemAction[] getToolBarActions() {
        return new SystemAction[] {
            SystemAction.get(StopCompileAction.class),
            SystemAction.get(FilterCompileErrorsAction.class),
            SystemAction.get(RemoveFilterAction.class),
            SystemAction.get(ExportAction.class)
        };
    }

    public void updateFilterCount() {
        int all = TLUtils.getChildrenCountRecursively(rootNode);
        int shown = TLUtils.getChildrenCountRecursively(
            getExplorerManager().getExploredContext());
        int filtered = all - shown;

        ProgressPanel panel = (ProgressPanel) getNorthComponent();
        panel.setErrors(nerr, nwarn, ninfo, filtered);
    }

    public Filter createFilter() {
        return new CompileErrorFilter();
    }

    protected TaskAnnotation getAnnotation(Task task) {
        return new CompileErrorAnnotation((CompileError) task, this);
    }

    public void setNorthComponentVisible(boolean v) {
        if (!v)
            return;
        else
            super.setNorthComponentVisible(true);
    }

    protected Component createNorthComponent() {
        return new ProgressPanel();
    }

    protected void componentDeactivated() {
        super.componentDeactivated();
        try {
            String ctxName = "/Settings/org/netbeans/modules/tasklist/compiler"; // NOI18N
            Context ctx = Context.getDefault().createSubcontext(ctxName);
            // TODO leads to an exception ctx.putObject("Settings", settings); // NOI18N
        } catch (ContextException e) {
            ErrorManager.getDefault().notify(e);
        }
    }

    protected void componentOpened() {
        super.componentOpened();
        
        loadColumnsConfiguration();
        
        if (initialized)
	    return;

        initialized = true;
        setNorthComponentVisible(true);

        if (!settings.javacRegExpUpdated) {
            NotifyDescriptor nd = new NotifyDescriptor.Confirmation(
                NbBundle.getMessage(CompileErrorsView.class,
                    "UpdateJavacRegexpQ"), // NOI18N
                NotifyDescriptor.YES_NO_OPTION
            );
            if (DialogDisplayer.getDefault().notify(nd) ==
                NotifyDescriptor.YES_OPTION) {
                UpdateJavacRegexpAction a = (UpdateJavacRegexpAction)
                    SystemAction.get(UpdateJavacRegexpAction.class);
                a.performAction();
            }
            settings.javacRegExpUpdated = true;
        }
    }

    protected Component createCenterComponent() {
        if (columns == null) {
            columns = createColumns();
        }
        ErrorsTreeTable tt = new ErrorsTreeTable(
            getExplorerManager(), columns, getEffectiveRoot());
        
        treeTable = tt;

        final JScrollPane sp = new JScrollPane((Component) treeTable,
            JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, 
            JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        
        sp.addMouseListener(new MouseUtils.PopupMouseAdapter() {
            public void showPopup(MouseEvent e) {
                Action[] actions = new Action[] {
                    SystemAction.get(FilterAction.class),
                    SystemAction.get(ExportAction.class),
                    SystemAction.get(UpdateJavacRegexpAction.class)
                };
                JPopupMenu pm = Utilities.actionsToPopup(actions, sp);
                pm.show(sp, e.getX(), e.getY());
            }
        });
        
        ChooseColumnsPanel.installChooseColumnsButton(sp);
        return sp;
    }

    protected Node createRootNode() {
        LOGGER.log(Level.FINE, "creating root node", new Exception()); // NOI18N
//        CompileError root = (CompileError) getModel().getRoot();
//        return new BuildRootNode(root);
        return new TaskListNode(getModel());
    }

    protected ColumnProperty[] createColumns() {
        ColumnProperty summary = new ColumnProperty(
	    0, // UID -- never change (part of serialization)
            CompileErrorNode.PROP_SUMMARY,
            rb.getString("Summary"), // NOI18N
            rb.getString("SummaryHint"), // NOI18N
	    true, 600
        );
        ColumnProperty details = new ColumnProperty(
	    1, // UID -- never change (part of serialization)
            CompileErrorNode.PROP_DETAILS,
            String.class,
            rb.getString("Details"), // NOI18N
            rb.getString("DetailsHint"), // NOI18N
	    true, false, 400
        );
        details.setPropertyEditorClass(StringPropertyEditor.class);
        ColumnProperty line = new ColumnProperty(
	    2, // UID -- never change (part of serialization)
            CompileErrorNode.PROP_LINE,
            Line.class,
            rb.getString("Line"), // NOI18N
            rb.getString("LineHint"), // NOI18N
	    true, true, 40
        );
        ColumnProperty column = new ColumnProperty(
	    3, // UID -- never change (part of serialization)
            CompileErrorNode.PROP_COLUMN,
            Integer.class,
            rb.getString("Column"), // NOI18N
            rb.getString("ColumnHint"), // NOI18N
	    true, false, 40
        );
        ColumnProperty file = new ColumnProperty(
	    4, // UID -- never change (part of serialization)
            CompileErrorNode.PROP_FILE,
            FileObject.class,
            rb.getString("File"), // NOI18N
            rb.getString("FileHint"), // NOI18N
	    true, true, 200
        );
        ColumnProperty folder = new ColumnProperty(
	    5, // UID -- never change (part of serialization)
            CompileErrorNode.PROP_FOLDER,
            FileObject.class,
            rb.getString("Folder"), // NOI18N
            rb.getString("FolderHint"), // NOI18N
	    true, false, 400
        );
        ColumnProperty severity = new ColumnProperty(
	    6, // UID -- never change (part of serialization)
            CompileErrorNode.PROP_SEVERITY,
            Integer.class,
            rb.getString("Severity"), // NOI18N
            rb.getString("SeverityHint"), // NOI18N
	    true, false, 19
        );
        severity.setValue(NodesTreeTable.RENDERER_KEY, 
            new SeverityTableCellRenderer());
        return new ColumnProperty[] {
            summary, details, folder, file, line, column, severity
        };
    }

    public void compilationStarted(CompilerTask task) {
        nerr = nwarn = ninfo = 0;
        ProgressPanel panel = (ProgressPanel) getNorthComponent();
        panel.setErrors(0, 0, 0, 0);
        panel.setProgressBarVisible(true);
        setStatusText(compStarted.format(taskToArgs(task)));
        if (defBuildProcess != null) {
            defBuildProcess.clear();
        } else {
            // TODO I18N
            defBuildProcess = new BuildProcess("Default build process");
            ((TaskList)getModel()).appendTask(defBuildProcess);
        }
        
        treeTable.expandNode(getExplorerManager().getRootContext());
        Node[] p = findPathToProcess(defBuildProcess);
        if (p != null) {
            treeTable.expandNode(p[p.length - 1]);
        }
        
        hideTaskInEditor();
    }

    public void progress(float a) {
        int n = Math.round(a * 100);
        ProgressPanel panel = (ProgressPanel) getNorthComponent();
        panel.setProgress(n);
    }

    public void compilerProgress(ProgressEvent ev) {
        // choose right message
        String status = null;
        switch (ev.getTask()) {
            case ProgressEvent.TASK_PARSING:
                status = parsing;
                break;
            case ProgressEvent.TASK_WRITING:
                status = writing;
                break;
            case ProgressEvent.TASK_GENERATING:
                status = generating;
                break;
            case ProgressEvent.TASK_CLEANING:
                status = cleaning;
                break;
            default:
                status = parsing;
                break;
        }
        if (status == null) return;
        Object[] args = new Object[] {
            status,
            ev.getFile().getPath()
        };
        String msg = compilingMsg.format (args);
        setStatusText (msg);
    }

    public void compilerError(ErrorEvent ev) {
        // XXX HACK for empty messages
        if (ev.getMessage().trim().length() == 0)
            return;

        // XXX HACK javac message like "10 errors"
        if (javacInfos.matcher(ev.getMessage()).matches())
            return;
        
        CompileError err = new CompileError(ev);
        switch (err.getSeverity()) {
            case CompileError.SEVERITY_ERROR:
                nerr++;
                break;
            case CompileError.SEVERITY_WARNING:
                nwarn++;
                break;
            case CompileError.SEVERITY_INFO:
                ninfo++;
                break;
            default:
                throw new InternalError("Wrong severity"); // NOI18N
        }
        
        if (!this.isShowing()) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    showInMode();
                }
            });
        }

        defBuildProcess.addSubtask(err, true);

        int all = TLUtils.getChildrenCountRecursively(rootNode);
        int shown = TLUtils.getChildrenCountRecursively(
            getExplorerManager().getExploredContext());
        int filtered = all - shown;

        ProgressPanel panel = (ProgressPanel) getNorthComponent();
        panel.setErrors(nerr, nwarn, ninfo, filtered);
    }

    public void compilationFinished(CompilerTask task, boolean uptodate) {
        ProgressPanel panel = (ProgressPanel) getNorthComponent();
        panel.setProgressBarVisible(false);
        MessageFormat msg = task.isSuccessful() ? compSuccess : compUnsuccess;
        String fimsg = msg.format(taskToArgs(task));

        // find and show first error
        if (nerr != 0) {
            Iterator it = getModel().getTasks().iterator();
            while (it.hasNext()) {
                CompileError err = (CompileError) it.next();
                if (err.getSeverity() == CompileError.SEVERITY_ERROR) {
                    select(err);
                    showTaskInEditor(err, new CompileErrorAnnotation(err));
                    break;
                }
            }
        }

        if (nerr == 0 && nwarn == 0 && isShowing()) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    close();
                }
            });
        }

        setStatusText(fimsg);
    }

    /**
     * Finds child node corresponding to the specified build message
     *
     * @param parent parent node
     * @param e build message
     * @return child node or null
     */
    private static Node findChildNode(Node parent, CompileError e) {
        Node[] ch = parent.getChildren().getNodes();
        for (int i = 0; i < ch.length; i++) {
            if (TaskNode.getTask(ch[i]) == e) {
                return ch[i];
            }
        }
        return null;
    }
    
    /**
     * Finds the path to the specified build process
     *
     * @param e build process
     */
    private Node[] findPathToProcess(BuildProcess e) {
        BuildRoot r = (BuildRoot) e.getParent();
        
        Node rootNode = getExplorerManager().getRootContext();
        Node processNode = findChildNode(rootNode, e);
        if (processNode == null)
            return null;
        
        return new Node[] {
            rootNode, processNode
        };
    }
    
    /**
     * Finds the path to the specified build message
     *
     * @param e build message
     */
    private Node[] findPathToMessage(CompileError e) {
        BuildProcess p = (BuildProcess) e.getParent();
        BuildRoot r = (BuildRoot) e.getParent();
        
        Node rootNode = getExplorerManager().getRootContext();
        Node processNode = findChildNode(rootNode, p);
        if (processNode == null)
            return null;
        Node msgNode = findChildNode(processNode, e);
        if (msgNode == null)
            return null;
        
        return new Node[] {
            rootNode, processNode, msgNode
        };
    }
    
    /**
     * Sets new status text.
     *
     * @param text new status text
     */
    private void setStatusText(String text) {
        String line = oneLine(text);
        if (!isShowing()) {
            statusTextSet = true;
            StatusDisplayer.getDefault().setStatusText(line);
        } else {
            if (statusTextSet) {
                statusTextSet = false;
                StatusDisplayer.getDefault().setStatusText(""); // NOI18N
            }
        }
        if (defBuildProcess != null) {
            defBuildProcess.setSummary(line);
        }
    }

    /**
     * Creates an array with arguments for message formatting.
     *
     * @param task a compiler task
     * @return objects for message formatting
     */
    private static Object[] taskToArgs(CompilerTask task) {
        String name = ((MyCompilerTask) task).getName();
        return new Object[] {
            name,
            "".equals(name) ? new Integer(0) : new Integer(1) // NOI18N
        };
    }

    /**
     * Removes newlines from the string
     *
     * @param txt text
     * @return converted text
     */
    private static String oneLine(final String txt) {
        StringBuffer sb = new StringBuffer(txt.length());
        boolean lastIsNewline = false;
        for (int i = 0; i < txt.length(); i++) {
            char ch = txt.charAt(i);
            if (ch == '\n' || ch == '\r') {
                if (! lastIsNewline) {
                    lastIsNewline = true;
                    sb.append(' ');
                }
            } else {
                sb.append(ch);
                lastIsNewline = false;
            }
        }
        return sb.toString();
    }

    public HelpCtx getHelpCtx() {
        return new HelpCtx("org.netbeans.modules.tasklist.compiler"); // NOI18N
    }

    protected void storeColumnsConfiguration() {
        ColumnsConfiguration columns = getDefaultColumns();
        ((ErrorsTreeTable) treeTable).save(columns);
    }
    
    protected void loadColumnsConfiguration() {
        if (!(treeTable instanceof ErrorsTreeTable))
            return;
        
        ErrorsTreeTable ett = (ErrorsTreeTable) treeTable;
        ColumnsConfiguration columns = getDefaultColumns();
        ett.configure(columns);
    }
    
    public void readExternal(java.io.ObjectInput in) throws java.io.IOException, 
    ClassNotFoundException {
        super.readExternal(in);        
    }    
}
... 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.