Geertjan's Blog

  • November 24, 2010

Hyperlink in a Plain Text File

Geertjan Wielenga
Product Manager
Let's say you want to create a hyperlink in a plain text file, like this:

Here's how:

import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
import javax.swing.text.StyledDocument;
import org.netbeans.api.editor.EditorRegistry;
import org.netbeans.lib.editor.hyperlink.spi.HyperlinkProvider;
import org.openide.util.Exceptions;
public class RoutesHyperlinkProvider implements HyperlinkProvider {
private static String ROUTES_IDENTIFIER = "Application.index";
private int startOffset;
private int endOffset;
public boolean isHyperlinkPoint(Document doc, int offset) {
Pattern p = Pattern.compile(ROUTES_IDENTIFIER);
try {
Matcher m = p.matcher(doc.getText(0, doc.getLength()));
while (m.find() == true){
startOffset = m.start();
endOffset = m.end();
return true;
} catch (BadLocationException ex) {
return false;
public int[] getHyperlinkSpan(Document dcmnt, int i) {
JTextComponent target = EditorRegistry.lastFocusedComponent();
final StyledDocument styledDoc = (StyledDocument) target.getDocument();
if (styledDoc == null) {
return null;
// Return the position which was set in the isHyperlink method:
return new int[]{startOffset, endOffset};
public void performClickAction(Document dcmnt, int i) {
//do something when the user clicks the hyperlink

Join the discussion

Comments ( 3 )
  • Emilian Bold Wednesday, November 24, 2010

    It seems you code only supports a single ROUTES_IDENTIFIER in the document -- what happens if there are more ?

    If it's only one, then the 'while' in 'isHyperlinkPoint' might as well be replaced with an 'if'.

    Also, not sure why you are using 'EditorRegistry.lastFocusedComponent()' in 'getHyperlinkSpan' when it seems you are given a 'Document dcmnt' argument.

    You are also given an 'offset' which you never use and should probably make matching faster if you just get a substring from the document and not the whole text. Another trick might be to cache the compiled pattern.

    Well, that was my code review so far :-)

  • Geertjan Wielenga Wednesday, November 24, 2010

    That's exactly the problem I have, i.e., I only support a single ROUTES_IDENITIFIER. Can someone give me a tip what I should do to support more?

  • Carlos Hoces Thursday, November 25, 2010

    This could be a prototype for a more general implementation:

    public abstract class AbstractHyperlinkProvider implements HyperlinkProvider {

    private transient int startOffset, endOffset;

    private transient final String identifier;


    public abstract void performClickAction(Document document, int i);

    public AbstractHyperlinkProvider(String identifier) {

    this.identifier = identifier;



    public boolean isHyperlinkPoint(Document document, int offset) {

    boolean result = false;

    Matcher matcher = null;

    try {

    matcher = Pattern.compile(identifier).matcher(document.getText(0, document.getLength()));

    } catch (BadLocationException ex) {



    while (matcher.find()) {

    startOffset = matcher.start();

    endOffset = matcher.end();

    result = true;



    return result;



    public int[] getHyperlinkSpan(Document document, int i) {

    int[] result = null;

    if ((StyledDocument) EditorRegistry.lastFocusedComponent().getDocument() != null) {

    // Return the position which was set in the isHyperlink method:

    result = new int[]{startOffset, endOffset};


    return result;


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.