Geertjan is a DZone Zone Leader and has posted 466 posts at DZone. You can read more from them at their website. View Full User Profile

How to Add Syntax Coloring for XML in the Lobo Java Web Browser

02.08.2008
| 10980 views |
  • submit to reddit

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!

 

Published at DZone with permission of its author, Geertjan Wielenga.

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

Jose, thanks, you've answered all my questions. Can you just explain a bit more about the title? I wondered about that. What's the other method I can use? A small code snippet on this point would be very helpful. About the licensing -- I thought about that too and will try to find out what the situation is exactly in terms of Batik licensing. By the way, can you tell me exactly where the repository is where I can get all the Lobo browser sources? I'd like to download all the sources and take a look at them. Thanks for your interest in my experiments and thanks also for the browser itself.

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

Hi Kirill. That works for me if I add it to the XmlContext class, within the library itself. Not sure if the library has developed since the time I first downloaded it, because the version I have is from the time it was first committed to Batik. The fonts you refer to all work for me, but, again, only if I change the font within the XmlContext class within the library, not the implementation of it, which is where it should be put.

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:

public void setSyntaxForeground(Map<String,Color> syntaxForegroundMap)

public void setSyntaxFont(Map<String,Font> syntaxFontMap)

 

@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:

java.awt.GraphicsEnvironment.registerFont(Font font) // as specified by Java API docs 1.6

 

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

تحميل برامج برامج جوالات العاب بنات برامج تكنولوجيا كتب تعليم UltraSurf العاب برامج نت Internet Download Manager ProgDVB برامج مجانية أفضل المواقع العربية دليل مواقع مشاهدة محطات مشفرة Online TV Player 3.0.0.940 Internet Download Manager 5.17 Build 4 رقص شرقي anyTV Pro 4.32 OnLineLive 7.1.1 هزي يانواعم ProgDVB 6.06.2 SopCast 3.0.3 منتدى برامج نت Falco Image Studio 3.6 لعبة تزلج على الجليد UltraSurf 9.4 كاثرين هيغل Katherine Heigl محطة غنوة FreeZ Online TV 1.0 Free Video to Mp3 Converter 3.1.3.51 Advanced MP3 Converter 2.10 Xilisoft Video to Audio Converter 5.1.23.0515 Blaze Media Pro 8.02 AKRAM Media Creator 1.11 DVD Audio Extractor 4.5.4 Free WMA to MP3 Converter 1.16 لعبة نينجا المتقدم لعبة قذف كرة لعبة دراجات البهلوانية لعبة اعداء الغابة تحميل برامج Download DivX Subtitles 2.0 BullGuard 8.5 Google Chrome 2.0.181.1 Dev Dell Studio XPS Desktop 435T Intel Matrix Storage Manager A00 Gigabyte GA-EP45-UD3P Bios F9 Ambush HDConvertToX 1.1.229.1764 MSI Wind Nettop CS 120 Realtek Audio Driver 5.10.0.5618 Biostar T41-A7 6.x Realtek On-Board Audio Driver 5.10.0.5735 for 2000/2003/XP TweakNow RegCleaner 4.1.1 SpeedItup Free 4.97 برامج العاب - Internet Download Manager - برامج جوالات - العاب - محطة غنوة - قنوات فضائية - بنات - تكنولوجيا - كتب تعليم - UltraSurf - ق ذ -0

jiji530 (not verified) replied on Mon, 2009/06/29 - 9:46pm

thanks for your post.perhaps you will like abercrombie ed hardy mortgage rates tiffanys ed hardy Is not it?

Reginald Carter replied on Tue, 2009/11/24 - 6:21pm

Hi- I am just starting to familiarize myself with Lobo and like your explanation for creating plugins that extend the browser's rendering capabilities.I decided to try using JavaEditorKit by Timothy Prinzing at Sun Microsystems.My ExtensionImpl.java looks like this:
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:

public class ExtensionImpl extends org.lobobrowser.primary.ext.ExtensionImpl

instead of :

public class ExtensionImpl implements NavigatorExtension

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

This might be really useful. This is the first time I encountered this application. Good thing I stumbled upon in your post. - Joe Aldeguer

Lucifer Williams replied on Thu, 2012/11/15 - 4:29pm

Nevertheless team building strategies, 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.

Ahmed Hashem replied on Wed, 2014/08/13 - 5:53am

good info really

العاب تلبيس باربي

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.