Home > Articles > Programming > Java

  • Print
  • + Share This
This chapter is from the book

7.2 Example: Simple Prime Tag

In this example we create a simple custom tag that would output a random 50-digit prime number to the JSP page (a real treat!). We accomplish this task with the help of the Primes class shown in Listing 7.4.

We define a tag handler class SimplePrimeTag that extends the SimpleTagSupport class. In its doTag method, we obtain a reference to the JspWriter by calling getJspContext().getOut(). Then, by using the static method Primes.nextPrime we generate our random 50-digit prime number. We output this number to the JSP page by invoking the print method on the JspWriter object reference. The code for SimplePrimeTag.java is shown in Listing 7.5.

Listing 7.4. Primes.java

package coreservlets;
import java.math.BigInteger;

/** A few utilities to generate a large random BigInteger,
 *  and find the next prime number above a given BigInteger.
 */
public class Primes {
  private static final BigInteger ZERO = BigInteger.ZERO;
  private static final BigInteger ONE = BigInteger.ONE;
  private static final BigInteger TWO = new BigInteger("2");

  // Likelihood of false prime is less than 1/2^ERR_VAL
  // Presumably BigInteger uses the Miller-Rabin test or
  // equivalent, and thus is NOT fooled by Carmichael numbers.
  // See section 33.8 of Cormen et al.'s Introduction to
  // Algorithms for details.
  private static final int ERR_VAL = 100;

  public static BigInteger nextPrime(BigInteger start) {
    if (isEven(start))
      start = start.add(ONE);
    else
      start = start.add(TWO);
    if (start.isProbablePrime(ERR_VAL))
      return(start);
    else
      return(nextPrime(start));
  }

  private static boolean isEven(BigInteger n) {
    return(n.mod(TWO).equals(ZERO));
  }

  private static StringBuffer[] digits =
    { new StringBuffer("0"), new StringBuffer("1"),
      new StringBuffer("2"), new StringBuffer("3"),
      new StringBuffer("4"), new StringBuffer("5"),
      new StringBuffer("6"), new StringBuffer("7"),
      new StringBuffer("8"), new StringBuffer("9") };
  private static StringBuffer randomDigit(boolean isZeroOK) {
    int index;
    if (isZeroOK) {
      index = (int)Math.floor(Math.random() * 10);
    } else {
      index = 1 + (int)Math.floor(Math.random() * 9);
    }
    return(digits[index]);
  }

  /** Create a random big integer where every digit is
   *  selected randomly (except that the first digit
   *  cannot be a zero).
   */
  public static BigInteger random(int numDigits) {
    StringBuffer s = new StringBuffer("");
    for(int i=0; i<numDigits; i++) {
      if (i == 0) {
        // First digit must be non-zero.
        s.append(randomDigit(false));
      } else {
        s.append(randomDigit(true));
      }
    }
    return(new BigInteger(s.toString()));
  }

  /** Simple command-line program to test. Enter number
   *  of digits, and it picks a random number of that
   *  length and then prints the first 50 prime numbers
   *  above that.
   */

  public static void main(String[] args) {
    int numDigits;
       try {
        numDigits = Integer.parseInt(args[0]);
      } catch (Exception e) { // No args or illegal arg.
        numDigits = 150;
      }
      BigInteger start = random(numDigits);
      for(int i=0; i<50; i++) {
        start = nextPrime(start);
        System.out.println("Prime " + i + " = " + start);
      }
   }
}

Listing 7.5. SimplePrimeTag.java

package coreservlets.tags;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.*;
import java.math.*;
import coreservlets.Primes;

/**
 *  SimplePrimeTag output a random 50-digit prime number
 *  to the JSP page.
 */
public class SimplePrimeTag extends SimpleTagSupport {
  protected int length = 50;

  public void doTag() throws JspException, IOException {
    JspWriter out = getJspContext().getOut();
    BigInteger prime = Primes.nextPrime(Primes.random(length));
    out.print(prime);
    }
}

Now that we have our tag handler class, we need to describe our tag to the container. We do this using the TLD csajsp-taglib.tld shown in Listing 7.6. Because all our tag does is output a prime number, we don't need to allow the tag to include a body, and so we specify empty as the value of the body-content element. We place the csajsp-taglib.tld file in the WEB-INF/tlds folder.

Listing 7.6. Excerpt from csajsp-taglib.tld

<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
  http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
  version="2.0">
  <tlib-version>1.0</tlib-version>
  <short-name>csajsp-taglib</short-name>

  <tag>
    <description>Outputs 50-digit primes</description>
    <name>simplePrime</name>
    <tag-class>coreservlets.tags.SimplePrimeTag</tag-class>
   <body-content>empty</body-content>
  </tag>
  ...
</taglib>

Listing 7.7 shows the simple-primes-1.jsp page, which uses the simple prime tag. We assign csajsp as the prefix for all tags (so far just simplePrime) in the /WEB-INF/tlds/csajsp-taglib.tld library. Also note that it is perfectly legal to use a closing tag with the body-content of empty as long as there is nothing, not even a space, between the opening tag and the closing tag, as shown by the last occurrence of the tag in the simple-primes-1.jsp page; that is, <csajsp:simplePrime></csajsp:simplePrime>. The resulting output is shown in Figure 7-1.

Listing 7.7. simple-primes-1.jsp

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>Some 50-Digit Primes</TITLE>
<LINK REL=STYLESHEET
      HREF="JSP-Styles.css"
      TYPE="text/css">
</HEAD>
<BODY>
<H1>Some 50-Digit Primes</H1>
<%@ taglib uri="/WEB-INF/tlds/csajsp-taglib.tld"
            prefix="csajsp" %>
<UL>
  <LI><csajsp:simplePrime />
  <LI><csajsp:simplePrime />
  <LI><csajsp:simplePrime />
  <LI><csajsp:simplePrime></csajsp:simplePrime>
</UL>
</BODY></HTML>
Figure 7-1

Figure 7-1 Result of simple-primes-1.jsp.

  • + Share This
  • 🔖 Save To Your Account