Categories
frameworks

Growing Frameworks: Plugins

What
 
Why
                vs external program
                vs source code
 
Mechanics of plugin client
                Code to interface
                Move class files to plugin directory
                Watch it work
 
Mechanics of server
                Define interface
                Define directory
                Load classes
                Instantiate & call
 
Plugins in Java
 
Consequences
                Security
                Security Manager
                CPU
 
Applications in the Site Manager
 
 

Plugins

Sometimes, we’d like to treat a whole application as a black-box framework. We might like a sophisticated end user to be able to extend the application.
 
A plugin is code, typically developed by a framework user, that provides extra capabilities to an application. It is useful when the application provides a framework (in the broadest sense), but different users might need their own handling of the details.
 
Adobe Photoshop™, a top-end graphics tool, is probably the biggest popularizer of the plugin approach. Adobe didn’t want to be responsible for creating and marketing every cool image filter imaginable. Instead, they provide a mechanism where you can buy a plugin from a third party, and install it into Photoshop. The plugin becomes a new tool available to the user, as if it had been built in originally.
 
A “traditional” way to provide such a feature is to provide a pipeline to a separate process. For example, web servers have traditionally used CGI scripts in this way. When a web page is requested that uses a CGI script, the web server creates a process for the script, builds a pipeline to it, sends the script the data from the request, and sends the output of the pipline as the result of the request.
 
Separate process
Advantages
Disadvantages
·         Well-defined interface.
·         Separate address space prevents a bad script from crashing the whole process.
·         Separate address space requires explicit transfer of information.
·         Creating processes adds overhead (mitigated by pooling).
·         May require multiple copies of data.
 
An alternative is to use threads, running the script in a separate thread within the server.
 
 
Separate thread in one process
Advantages
Disadvantages
·         Well-defined interface.
·         Easier to pass information to the script.
·         Less overhead to create thread (rather than process).
·         Trouble in one thread can hurt the whole process.
·         The thread has access to the internals of the whole application.
 
In Java, servlets take this approach. (Because Java is a relatively safe language, we run less risk of the script crashing the server than we would for, say, C programs.) Some web servers, such as Apache, have been modified to take this approach for languages other than Java.
 
Another alternative would be to provide the whole framework of the application.
 
Make whole framework/application available
Advantages
Disadvantages
·         Allows developer to control all aspects.
 
·         Requires developer to control all aspects.
·         Gives away too much intellectual property.
 
 
A plugin provides an intermediate point in this design space.
 
·         Only part of the application framework is exposed. The preserves much of the developer’s intellectual property, but still exposes a well-defined piece. (This exposure is the price of letting others extend the application.)
·         The plugin code typically runs in the main thread, or a separate thread in the application. It is quick enough to start up that it can be used to extend a menu or palette.
·         “Integration” of the plugin with the application is done at run-time. (The developer has to integrate and test with the application, but to the end user it’s “plug-n-play”.)
 
We’ll look at plugins from the perspective of the end user, the plugin developer, and the framework developer. We’ll explore how  plugins can be implemented in Java. Finally, we’ll add plugin support to the web site manager we developed in a previous chapter.
 

Plugins as Seen by the End-User

 
Plugins are simple from the end-user’s point of view. The user has the main application, and decides to add a plugin. Once the plugin is installed, the user has a new feature in the application.
 
How does the user install the plugin? Several possibilities are common:
·         The main application detects the need for the plugin, and asks permission to  install it. (Netscape Communicator (TM) does this.)
·         The user can instruct the main application to install a new plugin. The main application typically  uses a file dialog to help the user locate the plugin.
·         The plugin may control the process, by having an installation program the user must run. (Then the user is often prompted to locate the main application.)
·         Installation is “by convention.” The user may be instructed to drag a file (or files) to a particular directory of the main application.
 
Any of these mechanisms are workable. The key is to make it easy for the user.
 
 

Plugins as Seen by the Plugin Developer

The plugin developer typically works with a software development kit (SDK) for the plugin, provided by the developer of the main application.
 
The SDK will contain documentation, source code, object code, miscellaneous scripts and tools, and most importantly, examples. (Some SDKs will include tools such as compilers.)
 
The plugin developer will need to know the interface to which the plugin code must conform. (In Java, this will often be a Java “interface”, rather than inheriting from a particular class.) There may be important support classes as well. There may be information passed to the plugin that the plugin must understand.
 
The first example is the most critical. It’s the equivalent of “Hello, World” in C. It needn’t do much, but when the developer completes the steps, they will have created and installed a plugin from scratch.
 
Once completed, the plugin developer will test the plugin, and develop an installation mechanism (if one isn’t provided by the application directly).
 
 
 

Plugins as Seen by the Framework/Application Developer

The framework developer must define the interface for the plugin developer. In many ways, this is similar to defining any other framework interface. You want to keep it “narrow” – dependent on as few types as possible. This way, you only expose a limited amount of information to the plugin developer.
 
An easy way to allow for plugins is to designate a directory as the target location. This should be in the tree of class files: the plugin mechanism must be able to locate them.
 
The framework needs a mechanism for loading the plugin files. (We’ll see the details in the next section.)
 
                                Locate the plugins
                                Load their classes
                                Instantiate and hook up instances
 
Once instantiated, the plugins look like any other class. Usually, they’re added to a special menu or palette, to make them available to the end user at runtime.
 
Next, the framework developer must develop documentation and examples, as described in the previous section.
 
[TBD: The SDK]
 

 

Plugins in Java

Set directory
Class.forName(“file”) -> Class
Class.newInstance()
 
Use reflection:
Class c = Class.forName(“Package.classname”);
Object o = c.newInstance();
MyClass c = (MyClass) obj;
 
 
 

The Site Manager as a Plugin

 
 
Site manager plugins:
·         Look up plugins
·         Create main form
·         For each plugin, make listener & insert panel
·         Select top node
 
 
Make graph:
  getCanReverseLinks()
to tell if in-links accessible.
 
If false, enum always empty (not null).
 
 
PageSelectionListener
 
PageHandler implements PageSelectionListener
  void pageSelected (PageSelectionEvent e) { …}
 
 
Page view Plugin extends PageSelectionListener
                No-arg constructor () required
                void pageSelected (PageSelectionEvent e) { …}
                String getShortName() { …}
                String getLongName() { …}
                JPanel getPanel() { …}
 
Or an ObjectSelectionListener?
 
PageScorePlugin
  columns
  values
  min?  max?
  Range limits? (red/yellow/green?)
  int valueFor (page)
 
 

Plugin

 
Root directory
Directory to search
Class to match
Return array of all classes in the list that match the class
 
 
DefaultMutableTreeNode
 
public class FileTree extends DefaultTreeModel {
   public FileTree(File base) {
                super(new FileTreeNode(base));
  }
}
 
public class FileTreeNode extends DefaultMutableTreeNode {
                public FileTreeNode(File base) { super(base); base.isDirectory();}
                protected boolean loaded;
                public int getChildCount() {
                                if (!loaded) {
                                                File thisFile = (File)userObject;
                                                String files[] = thisFile.list();
                                                for (int i = 0; i < files.length; i++) {
                                                                add(new FileTreeNode(new File(thisFile, files[i])));
                                                }
                                                loaded = true;
                                }
                                return super.getChildCount();
                }
 
Note:
·         File.toString() is full path
·         Not alphabetical
·         Method to select row given file
 

public class GraphBrowser extends JPanel  implements GraphListener {
                GraphBrowser(Graph)
                GraphBrowser(Graph, Node)
                GraphBrowser()                   –??
                addObjectSelectionListener (ObjectSelectionListener osl) { …}
                removeObjectSelectionListener(ObjectSelectionListener osl) { …}
                setGraph(Graph)
                setNode(Node)                    // may be null
}
 
 
UI:
                List                Label=current   List
 
 

Graph Browser

 
Graph graph = null
Node current = null
 
JList inList = new JList();    // single-sel
JList outList = new JList();                // single-sel
JLabel currentNode = new JLabel();
 
GraphBrowser() {
                setLayout(new GridLayout(1,3));
                add(new JScrollPane(inList));
                add(currentNode);
                add(new JScrollPane(outList));
}
 
GraphBrowser(Graph) { …}
GraphBrowser(Graph, Node) { …}
 
void setGraph (Graph g) { graph = g; setNode(null);}
 
void setNode (Node n) {
                if (current != n) {
                                inList.setModel(new listModel w/in-nodes for enum);
                                Object o = n.getUserObject();
                                currentNode.setText(n==null?””:n.toString());
                                outList.setModel(new model w/out-nodes);
                                fireSelectionChanged();
                }
}
 
Listeners must make the selection be the new node.
addObjectSelectionListener (osl o) { …}
removeObjectSelectionListener(osl O) { …}
 

NodeToFileTreeAdapter extends objectSelectionListener {
                public void objectSelected (ObjectSelectionEvent e) {
                                Node n = (Node)e.getSelection();
                                Page p = (Page)n.getUserObject();
                                File f = p.getFile();
                                find f in tree
                                Set selector to that
                }
}
 

PLUGINS – NETSCAPE

 
http://developer.netscape.com/docs/manuals/communicator/plugin/index.html
 
Checks directory
Registers
Queries to see if they can handle it
 
Check type
Load plugin
Initialize
Create instance
 
Plug-in methods: Functions you implement
Netscape methods: In Communicator, plugin calls them
Data structures
 
 
When does it apply?
Beans as programs