CHAPTER 6: 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
PluginsSometimes, 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.
An alternative is to use threads, running the script in a separate thread within the server.
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.
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 DeveloperThe 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 DeveloperThe 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 JavaSet 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
| ||||||||||||||||||
|
Copyright 1994-2010, William C. Wake - William.Wake@acm.org |