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 Nokia. Portions Copyright 2003-2004 Nokia.
 * All Rights Reserved.
 */

package org.netbeans.modules.enode;

import java.util.ArrayList;
import java.util.List;
import java.util.Iterator;

import javax.swing.Action;
import javax.swing.JComponent;
import javax.swing.JSeparator;

import org.openide.ErrorManager;
import org.openide.util.WeakListener;

import org.netbeans.api.enode.ExtensibleNode;
import org.netbeans.api.registry.*;

/**
 * Object that helps the ExtensibleNode to keep track of
 * the actions. The actions are read from the layer using Registry API.
 * @author David Strupl
 */
public class ExtensibleNodeActions {
    
    static final String SUBMENU_PREFIX = "SubMenu";

    /**
     * Our node.
     */
    private ExtensibleNode enode;
    
    /**
     * We hold a reference to the listener for preventing
     * the garbage collection.
     */
    private Listener listener;
    
    /** 
     * Cache for the actions
     */
    private Action[] actions;
    
    /**
     * Prevent the listeners to be attached more than once.
     */
    private boolean listenersAttached = false;
    
    /**
     * Just remember the parameter enode.
     */
    public ExtensibleNodeActions(ExtensibleNode enode) {
        this.enode = enode;
    }
    
    /** Reads actions from a JNDI context. Also adds a listener
     * to the context.
     * @param name of the context.
     * @return array of actions
     */
    public Action[] getActions() {
        if (actions != null) {
            return actions;
        }
        ArrayList arr = new ArrayList ();
        String paths[] = enode.getPaths();
        
        String cpaths[] = getCookiePaths();
        try {
            for (int i = 0; i < paths.length; i++) {
                String path = ExtensibleNode.E_NODE_ACTIONS + paths[i];
                scanContext(path, arr);
            }
            for (int i = 0; i < cpaths.length; i++) {
                String path = ExtensibleNode.E_NODE_ACTIONS + cpaths[i];
                scanContext(path, arr);
            }
        } catch (ContextException ce) {
            ErrorManager.getDefault().getInstance("org.netbeans.modules.enode").notify(ErrorManager.INFORMATIONAL, ce); // NOI18N
        }

        listenersAttached = true; // after successfull iteration
        actions = (Action[])arr.toArray(new Action[arr.size()]);
        return actions;
    }

    /**
     * Adds objects from the context with path to the list arr.
     */
    private void scanContext(String path, ArrayList arr) throws ContextException {
        Context con = Context.getDefault().createSubcontext(path);
        if (!listenersAttached) {
            ContextListener l1 = getContextListener(con);
            con.addContextListener(l1);
        }

        List objects = con.getOrderedObjects();
        Iterator it = objects.iterator();
        while (it.hasNext()) {
            Object obj = it.next();
            if (obj instanceof Action) {
                arr.add(obj);
                continue;
            }
            // special handling of separators since they are represented
            // as nulls in the actions array
            if (obj instanceof JSeparator) {
                arr.add(null);
                continue;
            }
            // general JComponents are wrapped in special actions
            if (obj instanceof JComponent) {
                arr.add(new ComponentAction((JComponent)obj));
                continue;
            }
            //
            if (obj instanceof Context) {
                Context c1 = (Context)obj;
                String n = c1.getContextName();
                if ((n != null) && (n.startsWith(SUBMENU_PREFIX)) && (n.length() > SUBMENU_PREFIX.length())) {
                    arr.add(new SubMenuAction(c1, n.substring(SUBMENU_PREFIX.length())));
                    continue;
                }
            }
        }
    }
    
    /**
     * Computes additional paths for actions configured
     * via adding an action to a cookie instance.
     */
    private String[] getCookiePaths() {
        String paths[] = enode.getPaths();
        ArrayList names = new ArrayList();
        for (int i = 0; i < paths.length; i++) {
            String path = ExtensibleNode.E_NODE_LOOKUP + paths[i];
            try {
                Context con = Context.getDefault().createSubcontext(path);
                if (!listenersAttached) {
                    ContextListener l1 = getContextListener(con);
                    con.addContextListener(l1);
                }

                List objects = con.getOrderedNames();
                names.addAll(objects);
            } catch (ContextException ce) {
                ErrorManager.getDefault().getInstance("org.netbeans.modules.enode").notify(ErrorManager.INFORMATIONAL, ce); // NOI18N
            }
        }

        return (String[])names.toArray(new String[names.size()]);
    }
    
    /**
     * Lazy initialization of the listener variable. This method
     * will return a weak listener.
     * The weak listener references the object hold
     * by the  listener  variable.
     */
    private ContextListener getContextListener(Object source) {
        if (listener == null) {
            listener = new Listener();
        }
        return (ContextListener)WeakListener.create(ContextListener.class, listener, source);
    }
    
    /**
     * Whatever happens in the selected context this listener only clears
     * the actions reference. This cause the list of actions to
     * be computed next time someone asks for them.
     */
    private class Listener implements ContextListener {
        public void attributeChanged(AttributeEvent evt) {
            actions = null;
        }
        
        public void bindingChanged(BindingEvent evt) {
            actions = null;
        }
        
        public void subcontextChanged(SubcontextEvent evt) {
            actions = null;
        }
    }
}
... 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.