Making Plugins Even Easier
The new plugin architecture makes it a two step process to deploy extensions to EditLive!:
- Upload the plugin files.
- Edit the page that embeds EditLive! and add a call to addPlugin.
That's not bad, but that second step is a pain, particularly if it's over a remote connection to the server. It would be really nice if we could just upload the files and have them magically be picked up. Turns out, with a little bit of code on the server that's easy to do. As an added bonus it will make the applet start up faster too.
The secret is to create a directory that is specifically for EditLive! plugins and have the server iterate through the files in that directory and add them as plugins. Lets take a look at an example - this is in Java but the concepts are pretty easy to apply in any language.
We'll assume that the plugins directory is available via http://example.com/eljplugins/
First, get the plugins directory as a File:
File pluginsDir = new File(getServletContext().getRealPath("/eljplugins/"));
Now we want to iterate through all the files in the plugins directory and work just on the XML files as they're the plugin descriptors we want to load. There may be other files in the directory like jar files or javascript files for the plugins that we want to skip.
File[] pluginConfigFiles = pluginsDir.listFiles(new FileFilter() {
public boolean accept(File testFile) {
return testFile.getName().endsWith(".xml");
}
});
Now that we have the list of plugin config files to load, for each one we read the file contents and add it as a plugin.
for (int i = 0; i < pluginConfigFiles.length; i++) {
try {
BufferedReader in = new BufferedReader(new FileReader(pluginConfigFiles[i]));
StringBuffer configContent = new StringBuffer();
for (String line = in.readLine(); line != null; line = in.readLine()) {
configContent.append(line);
configContent.append("\n");
}
out.println("elj.addPluginAsText('" +
URLEncoder.encode(configContent.toString()) + "',
'/eljplugins/" + pluginConfigFiles[i].getName() + "');\n");
} catch (Exception e) {
e.printStackTrace();
}
}
There's a fair bit going on there, the majority of it is just reading in the contents of the file. The important line is:
out.println("elj.addPluginAsText('" + URLEncoder.encode(configContent.toString()) + "',
'/eljplugins/" + pluginConfigFiles[i].getName() + "');\n");
This outputs a JavaScript call to addPluginAsText with two parameters:
- The URL encoded content of the plugin config file.
- The URL to the plugin config file. This is used to resolve relative references against so that the plugin resources can be found correctly.
The main catch with this code is that it doesn't correctly detect the character set from the XML config files and always uses the platform default setting. If you need to deal with international character sets in plugin config files, you'll need to add in code to handle that1.
Here's the entire code snippet:
File pluginsDir = new File(getServletContext().getRealPath("/eljplugins/"));
if (pluginsDir.exists()) {
File[] pluginConfigFiles = pluginsDir.listFiles(new FileFilter() {
public boolean accept(File testFile) {
return testFile.getName().endsWith(".xml");
}
});
for (int i = 0; i < pluginConfigFiles.length; i++) {
try {
BufferedReader in = new BufferedReader(
new FileReader(pluginConfigFiles[i]));
StringBuffer configContent = new StringBuffer();
for (String line = in.readLine(); line != null; line = in.readLine()) {
configContent.append(line);
configContent.append("\n");
}
out.println("elj.addPluginAsText('" +
URLEncoder.encode(configContent.toString()) + "',
'eljplugins/" + pluginConfigFiles[i].getName() + "');\n");
} catch(Exception e) {
e.printStackTrace();
}
}
}
Here's a similar function in PHP:
function loadPlugins($jsVariableName, $pluginDir, $pluginUrl) {
if (is_dir($pluginDir) && $dh = opendir($pluginDir)) {
while (($file = readdir($dh)) !== false) {
if (fnmatch("*.xml", $file)) {
$filename = $pluginDir . '/' . $file;
$content = file_get_contents($filename);
if ($content) {
$content = rawurlencode($content);
echo "$jsVariableName.addPluginAsText('$content', '$pluginUrl');\n";
}
}
}
closedir($dh);
}
}
1 - I'd recommend sticking with US-ASCII for plugin config files, you can always use XML entities if you need special characters and it makes it a lot easier for people to deploy the plugin.↩


June 5th, 2007 at 5:06 pm
[...] example (and others) can be installed and run using the Ephox Plug-in architecture (described in this liveworks article). As source filters work early in the documents lifecyle they should be loaded using the [...]