How to Add Syntax Coloring for XML in the Lobo Java Web Browser
Yesterday we explored the general approach by which plugins can be created for the rendering of new content types in Lobo's Java Web Browser. Today, let's take those general principles a step further and... color the syntax of XML shown in the Lobo browser. We will start by identifying the application/xml and text/xml MIME types and then integrate Batik's XML Editor, created by Tonny Kohar, into the browser. So, when you finish this article, you will have first class XML support for the Lobo browser.
Normally, when you open an XML file in the Lobo browser, you find that the XML is handled as plain text. However, the fact that you are able to open an XML file at all indicates that there must be a clientlet that handles XML (otherwise you'd get an error message as shown yesterday in the first illustration of the Manifest article). Nevertheless, I found that the plugin I created overwrites, somehow, the clientlet that already handles XML files. And the priority in the properties file has nothing to do with it, because I tried all different levels with the same outcome. So, I don't exactly understand how come mine overwrites the existing clientlet, but the fact that it does so is enough for me.
Hence, this is how an XML file is normally rendered:

So, the first step, as yesterday, is to create a new clientlet when NavigatorExtension.init identifies the XML MIME types:
private ClientletSelector selector;
private XmlClientlet xmlClient;
@Override
public void init(final NavigatorExtensionContext ctx) {
selector = new ClientletSelector() {
public Clientlet select(ClientletRequest request, ClientletResponse response) {
if (response.matches("text/xml", new String[]{""}) ||
response.matches("application/xml", new String[]{""})) {
xmlClient = new XmlClientlet();
return xmlClient;
}
return null;
}
public Clientlet lastResortSelect(ClientletRequest arg0, ClientletResponse arg1) {
return null;
}
};
ctx.addClientletSelector(selector);
}
Above, lines 9 and 10 identify our XML MIME types. Then I copied the whole content of the XML Editor from Batik's org.apache.batik.util.gui.xmleditor package. Now that I had the XML Editor in my sources, I was able to define the rendering, in my Clientlet definition, which is instantiated when the XML MIME type is identified:
public class XmlClientlet implements Clientlet {
@Override
public void process(ClientletContext context) throws ClientletException {
try {
InputStream in = context.getResponse().getInputStream();
try {
String text = IORoutines.loadAsText(in, "ISO-8859-1");
JEditorPane xmlEditorPane = new JEditorPane();
XMLEditorKit editorKit = new XMLEditorKit();
xmlEditorPane.setEditorKitForContentType(XMLEditorKit.XML_MIME_TYPE, editorKit);
xmlEditorPane.setContentType(XMLEditorKit.XML_MIME_TYPE);
Font defaultFont = new Font("Monospaced", Font.PLAIN, 12);
xmlEditorPane.setFont(defaultFont);
xmlEditorPane.setEditable(false);
xmlEditorPane.setBackground(Color.WHITE);
xmlEditorPane.setText(text);
JScrollPane pane = new JScrollPane(xmlEditorPane);
context.setResultingContent(pane);
} finally {
in.close();
}
} catch (IOException ioe) {
throw new ClientletException(ioe);
}
}
}
At this stage, my plugin's sources are as follows:
I then ran the browser, with my newly created JAR in the distro's ext folder, and now XML files look as follows:
If you want to take the plugin for a spin, here it is: LoboXMLClientletPlugin.jar . Put it in the Lobo distro's ext folder and then start the Lobo browser. Then open an XML file (either online or locally on disk)... and let me know if it works for you!





Comments
The Lobo Project replied on Fri, 2008/02/08 - 9:18am
I've been following your Lobo series with interest. You've done quite a bit of good work on the 3 recent articles.
As to why you're able to override the "text/xml" clientlet, that's a good question. It's purposefully allowed. Even though the primary extension has highest priority, you'll note a clientlet selector has both a select() and lastResortSelect() methods. The primary clientlet selector implements most of its logic in the lastResortSelect() method which is run after all other extensions have failed to provide clientlets.
Basically, only HTML (not XHTML) and image clientlets are non-overridable at the moment.
BTW, I put your plugin JAR in my local installation and I tried it with one of my Ant files. It looks pretty nice. It would be great to ship it with Lobo, but unfortunately I believe there's a license compatibility issue with Batik.
I noticed the title of the window is blank. When you set the resulting content, there's another method you can use where you can provide an object that has additional information about the component, such as the title, source code, and so on.
I think an important next step in the project is to come up with a more usable and secure mechanism to install plugins.
Jose
Geertjan Wielenga replied on Fri, 2008/02/08 - 9:48am
The Lobo Project replied on Fri, 2008/02/08 - 10:45am
in response to:
Geertjan Wielenga
The licensing issue is an annoying issue that comes up time and again with anything that has to do with the GPL/LGPL licenses and the views of FSF in regards to compatibility with various other licenses, most notably the Mozilla License and the Apache License. The FSF has a FAQ here:
http://www.gnu.org/philosophy/license-list.html
Someone recently suggested that I should look at OSGi as another mechanism to load plugins, and that sounded like a good idea, but the license of the better open source reference implementation of OSGi is the Apache License.
About the setResultingContent() method, note that there are two overloads. One takes a component, and the other takes a ComponentContent instance. ComponentContent is an interface but there's a SimpleComponentContent class you can use:
context.setResultingContent(new SimpleComponentContent(pane, "XML Document", text));
Instructions on how to get the full source code of the Lobo Project, setting up Eclipse to load the source code, and instructions on how to submit patches can be found here:
http://www.lobobrowser.org/sourcecode.jsp
Kirill Grouchnikov replied on Sat, 2008/02/09 - 6:56pm
Geertjan,
I tried to set a custom font on the editor pane and i don't see it being applied. This is how i load that font:
URL fontURL = classLoader.getResource("resource/VeraMono.ttf");
InputStream streamFont = fontURL.openStream();
Font font = Font.createFont(Font.TRUETYPE_FONT, streamFont);
font = font.deriveFont(13.0f);
Can you try it on your machine? The font is available at http://ftp.gnome.org/pub/GNOME/sources/ttf-bitstream-vera/1.10/
Thanks
Kirill
Geertjan Wielenga replied on Sun, 2008/02/10 - 5:00pm
in response to:
Kirill Grouchnikov
For example, here is VeraSeBd.tiff in action:
Tonny Kohar replied on Sun, 2008/02/10 - 11:47pm
@Geertjan
There were some improvement to the Batik XMLEditor especially in the area of extensibility, Now you can inherit from XMLContext and pass that context into the EditorKit constructor. So you do not need to always modify XMLContext, just inherit it, modify the things you are interested with and pass that into EditorKit constructor.
XMLContext also add new methods for setting syntax coloring during runtime eg:
@Kirill
The font rendering is handled by JEditorPane itself, not in our code, And I think your font loading should works. If it is not working maybe you need to register that font into the GraphicsEnvironment eg:
KIYUT imagine, design, create ... http://www.kiyut.com
Tonny Kohar replied on Mon, 2008/02/11 - 6:49am
in response to:
Jose Maria Arranz
@Jose
If you are looking for Java and SVG, you might be interested to check out Apache Batik
KIYUT imagine, design, create ... http://www.kiyut.com
Jose Maria Arranz replied on Mon, 2008/02/11 - 7:37am
in response to:
Tonny Kohar
Yes I know I know in fact I was talking about integrating Batik inside Lobo to render SVG, if Lobo is relicensed to GPL3 it can include Batik (GPL3 is compatible with Apache 2).
The Lobo Project replied on Tue, 2008/02/12 - 8:49am
in response to:
Jose Maria Arranz
Unfortunately, some parts of Lobo are third-party GPL or LGPL software, and those licenses are not compatible with GPLv3. It seems it would be difficult to upgrade to GPLv3.
Jose Maria Arranz replied on Tue, 2008/02/12 - 12:49pm
Try to contact with them, migrating to GPL3 is not a radical change.
aslan ozturk replied on Sun, 2008/06/08 - 8:18am
very nice article.
http://www.ankara-nakliyat.name.tr ankara evden eve nakliyat
jame jack replied on Mon, 2009/06/29 - 4:23pm
jiji530 (not verified) replied on Mon, 2009/06/29 - 9:46pm
Reginald Carter replied on Tue, 2009/11/24 - 6:21pm
package plugin; import org.lobobrowser.clientlet.Clientlet; import org.lobobrowser.clientlet.ClientletRequest; import org.lobobrowser.clientlet.ClientletResponse; import org.lobobrowser.clientlet.ClientletSelector; import org.lobobrowser.ua.NavigatorExtension; import org.lobobrowser.ua.NavigatorExtensionContext; import org.lobobrowser.ua.NavigatorWindow; public class ExtensionImpl extends org.lobobrowser.primary.ext.ExtensionImpl { private ClientletSelector selector; private JavaClientlet javaClient; @Override public void init(NavigatorExtensionContext ctx) { selector = new ClientletSelector() { public Clientlet select(ClientletRequest request, ClientletResponse response) { if (response.matches("text/java", new String[]{""})) { javaClient = new JavaClientlet(); return javaClient; } return null; } public Clientlet lastResortSelect(ClientletRequest arg0, ClientletResponse arg1) { return null; } }; ctx.addClientletSelector(selector); } @Override public void destroy() { // TODO Auto-generated method stub } @Override public void windowClosing(NavigatorWindow arg0) { // TODO Auto-generated method stub } @Override public void windowOpening(NavigatorWindow arg0) { // TODO Auto-generated method stub } }And my clientlet, like this:package plugin; import java.awt.Color; import java.awt.Font; import java.io.IOException; import java.io.InputStream; import javax.swing.JScrollPane; import jek.JavaEditorKit; import jek.JavaEditorPane; import org.lobobrowser.clientlet.Clientlet; import org.lobobrowser.clientlet.ClientletContext; import org.lobobrowser.clientlet.ClientletException; import org.lobobrowser.util.io.IORoutines; public class JavaClientlet implements Clientlet { public void process(ClientletContext context) throws ClientletException { try { InputStream in = context.getResponse().getInputStream(); try { String text = IORoutines.loadAsText(in, "ISO-8859-1"); JavaEditorPane jEditorPane = new JavaEditorPane(); JavaEditorKit editorKit = new JavaEditorKit(); jEditorPane.setEditorKitForContentType(editorKit.getContentType(),editorKit); jEditorPane.setContentType(editorKit.getContentType()); Font defaultFont = new Font("Monospaced", Font.PLAIN, 12); jEditorPane.setFont(defaultFont); jEditorPane.setEditable(false); jEditorPane.setBackground(Color.WHITE); jEditorPane.setText(text); JScrollPane pane = new JScrollPane(jEditorPane); context.setResultingContent(pane); } finally { in.close(); } } catch (IOException ioe) { throw new ClientletException(ioe); } } }I'm using Eclipse and cannot use the @Override annotation unless the class has a superclass containing the method to override.Which is why I use: instead of : At this point I have not been able to make it work. Possibly because I cannot use the @annotation with eclipse in my JavaClientlet class. Any feedback would be welcome.Carla Brian replied on Wed, 2012/05/09 - 9:25am
Lucifer Williams replied on Thu, 2012/11/15 - 4:29pm