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