ExampleTag.java Very simple custom tag. Remember to install it in the WEB-INF/classes/cwp/tags directory.

ExampleTag.java Very simple custom tag. Remember to install it in the WEB-INF/classes/cwp/tags directory. 


package cwp.tags;

import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.*;

/** Very simple JSP tag that just inserts a string
 *  ("Custom tag example...") into the output.
 *  The actual name of the tag is not defined here;
 *  that is given by the Tag Library Descriptor (TLD)
 *  file that is referenced by the taglib directive
 *  in the JSP file.
 *  <P>
 *  Taken from Core Web Programming Java 2 Edition
 *  from Prentice Hall and Sun Microsystems Press,
 *  .
 *  May be freely used or adapted.
 */

public class ExampleTag extends TagSupport {
  public int doStartTag() {
    try {
      JspWriter out = pageContext.getOut();
      out.print("Custom tag example " +
                "(cwp.tags.ExampleTag)");
    } catch(IOException ioe) {
      System.out.println("Error in ExampleTag: " + ioe);
    }
    return(SKIP_BODY);
  }
}

AccessCountBean.java Bean used to illustrate the difference between running jsp:setProperty for every request vs. only when the object is created

AccessCountBean.java Bean used to illustrate the difference between running jsp:setProperty for every request vs. only when the object is created

package cwp;

/** Simple bean to illustrate sharing beans through
 *  use of the scope attribute of jsp:useBean.
 *  <P>
 *  Taken from Core Web Programming Java 2 Edition
 *  from Prentice Hall and Sun Microsystems Press,
 *  .
 *  May be freely used or adapted.
 */

public class AccessCountBean {
  private String firstPage;
  private int accessCount = 1;

  public String getFirstPage() {
    return(firstPage);
  }

  public void setFirstPage(String firstPage) {
    this.firstPage = firstPage;
  }

  public int getAccessCount() {
    return(accessCount++);
  }
}

SaleEntry2.jsp Page that uses the SaleEntry bean, using the param attribute to read request parameters and assign them to bean properties

SaleEntry2.jsp Page that uses the SaleEntry bean, using the param attribute to read request parameters and assign them to bean properties

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- 
Example of using jsp:setProperty and an explicity association
with an input parameter. See SaleEntry1.jsp
and SaleEntry3.jsp for alternatives. 
   
Taken from Core Web Programming Java 2 Edition
from Prentice Hall and Sun Microsystems Press,
.
May be freely used or adapted.
-->
<HTML>
<HEAD>
<TITLE>Using jsp:setProperty</TITLE>
<LINK REL=STYLESHEET
      HREF="JSP-Styles.css"
      TYPE="text/css">
</HEAD>

<BODY>
<TABLE BORDER=5 ALIGN="CENTER">
  <TR><TH CLASS="TITLE">
      Using jsp:setProperty</TABLE>
<jsp:useBean id="entry" class="cwp.SaleEntry" />
<jsp:setProperty 
    name="entry"
    property="itemID"
    param="itemID" />
<jsp:setProperty 
    name="entry"
    property="numItems"
    param="numItems" />
<%-- WARNING! Both the JSWDK 1.0.1 and the Java Web Server
              have a bug that makes them fail on double
              type conversions of the following sort.
--%>
<jsp:setProperty 
    name="entry"
    property="discountCode"
    param="discountCode" />
<BR>
<TABLE ALIGN="CENTER" BORDER=1>
<TR CLASS="COLORED">
  <TH>Item ID<TH>Unit Price<TH>Number Ordered<TH>Total Price
<TR ALIGN="RIGHT">
  <TD><jsp:getProperty name="entry" property="itemID" />
  <TD>$<jsp:getProperty name="entry" property="itemCost" />
  <TD><jsp:getProperty name="entry" property="numItems" />
  <TD>$<jsp:getProperty name="entry" property="totalCost" />
</TABLE>     
</BODY>
</HTML>


SaleEntry.java //SaleEntry Bean

package cwp;

/** Simple bean to illustrate the various forms
 *  of jsp:setProperty.
 *  <P>
 *  Taken from Core Web Programming Java 2 Edition
 *  from Prentice Hall and Sun Microsystems Press,
 *  .
 *  May be freely used or adapted.
 */

public class SaleEntry {
  private String itemID = "unknown";
  private double discountCode = 1.0;
  private int numItems = 0;

  public String getItemID() {
    return(itemID);
  }

  public void setItemID(String itemID) {
    if (itemID != null) {
      this.itemID = itemID;
    } else {
      this.itemID = "unknown";
    }
  }

  public double getDiscountCode() {
    return(discountCode);
  }

  public void setDiscountCode(double discountCode) {
    this.discountCode = discountCode;
  }

  public int getNumItems() {
    return(numItems);
  }

  public void setNumItems(int numItems) {
    this.numItems = numItems;
  }

  // In real life, replace this with database lookup.

  public double getItemCost() {
    double cost;
    if (itemID.equals("a1234")) {
      cost = 12.99*getDiscountCode();
    } else {
      cost = -9999;
    }
    return(roundToPennies(cost));
  }

  private double roundToPennies(double cost) {
    return(Math.floor(cost*100)/100.0);
  }

  public double getTotalCost() {
    return(getItemCost() * getNumItems());
  }
}

SaleEntry.java Bean used to demonstrate the various approaches to reading request parameters and stuffing them into Java objects.

package cwp;

/** Simple bean to illustrate the various forms
 *  of jsp:setProperty.
 *  <P>
 *  Taken from Core Web Programming Java 2 Edition
 *  from Prentice Hall and Sun Microsystems Press,
 *  .
 *  May be freely used or adapted.
 */

public class SaleEntry {
  private String itemID = "unknown";
  private double discountCode = 1.0;
  private int numItems = 0;

  public String getItemID() {
    return(itemID);
  }

  public void setItemID(String itemID) {
    if (itemID != null) {
      this.itemID = itemID;
    } else {
      this.itemID = "unknown";
    }
  }

  public double getDiscountCode() {
    return(discountCode);
  }

  public void setDiscountCode(double discountCode) {
    this.discountCode = discountCode;
  }

  public int getNumItems() {
    return(numItems);
  }

  public void setNumItems(int numItems) {
    this.numItems = numItems;
  }

  // In real life, replace this with database lookup.

  public double getItemCost() {
    double cost;
    if (itemID.equals("a1234")) {
      cost = 12.99*getDiscountCode();
    } else {
      cost = -9999;
    }
    return(roundToPennies(cost));
  }

  private double roundToPennies(double cost) {
    return(Math.floor(cost*100)/100.0);
  }

  public double getTotalCost() {
    return(getItemCost() * getNumItems());
  }
}

The class that actually gets the strings over the network by means of an ObjectInputStream via HTTP tunneling.

import java.net.*;
import java.io.*;

/** When this class is built, it returns a value
 *  immediately, but this value returns false for isDone
 *  and null for getQueries. Meanwhile, it starts a Thread
 *  to request an array of query strings from the server,
 *  reading them in one fell swoop by means of an
 *  ObjectInputStream. Once they've all arrived, they
 *  are placed in the location getQueries returns,
 *  and the isDone flag is switched to true.
 *  Used by the ShowQueries applet.
 *  


 *  Taken from Core Web Programming Java 2 Edition
 *  from Prentice Hall and Sun Microsystems Press,
  *  May be freely used or adapted.
 */

public class QueryCollection implements Runnable {
  private String[] queries;
  private String[] tempQueries;
  private boolean isDone = false;
  private URL dataURL;

  public QueryCollection(String urlSuffix, URL currentPage) {
    try {
      // Only the URL suffix need be supplied, since
      // the rest of the URL is derived from the current page.
      String protocol = currentPage.getProtocol();
      String host = currentPage.getHost();
      int port = currentPage.getPort();
      dataURL = new URL(protocol, host, port, urlSuffix);
      Thread queryRetriever = new Thread(this);
      queryRetriever.start();
    } catch(MalformedURLException mfe) {
      isDone = true;
    }
  }

  public void run() {
    try {
      tempQueries = retrieveQueries();
      queries = tempQueries;
    } catch(IOException ioe) {
      tempQueries = null;
      queries = null;
    }
    isDone = true;
  }

  public String[] getQueries() {
    return(queries);
  }

  public boolean isDone() {
    return(isDone);
  }

  private String[] retrieveQueries() throws IOException {
    URLConnection connection = dataURL.openConnection();
    // Make sure browser doesn't cache this URL, since
    // I want different queries for each request.
    connection.setUseCaches(false);
    // Use ObjectInputStream so I can read a String[]
    // all at once.
    ObjectInputStream in =
      new ObjectInputStream(connection.getInputStream());
    try {
      // The return type of readObject is Object, so
      // I need a typecast to the actual type.
      String[] queryStrings = (String[])in.readObject();
      return(queryStrings);
    } catch(ClassNotFoundException cnfe) {
      return(null);
    }
  }
}

A class the encapsulates the URLs used by various search engines.

SearchSpec.java
*******************
/** Small class that encapsulates how to construct a
 *  search string for a particular search engine.
 *  Taken from Core Web Programming Java 2 Edition
 *  from Prentice Hall and Sun Microsystems Press,

 *  May be freely used or adapted.
 */

public class SearchSpec {
  private String name, baseURL, numResultsSuffix;

  private static SearchSpec[] commonSpecs =
    { new SearchSpec("google",
                     "http://www.google.com/search?q=",
                     "&num="),
      new SearchSpec("infoseek",
                     "http://infoseek.go.com/Titles?qt=",
                     "&nh="),
      new SearchSpec("lycos",
                     "http://lycospro.lycos.com/cgi-bin/" +
                        "pursuit?query=",
                     "&maxhits="),
      new SearchSpec("hotbot",
                     "http://www.hotbot.com/?MT=",
                     "&DC=")
    };

  public SearchSpec(String name,
                    String baseURL,
                    String numResultsSuffix) {
    this.name = name;
    this.baseURL = baseURL;
    this.numResultsSuffix = numResultsSuffix;
  }

  public String makeURL(String searchString,
                        String numResults) {
    return(baseURL + searchString +
           numResultsSuffix + numResults);
  }

  public String getName() {
    return(name);
  }

  public static SearchSpec[] getCommonSpecs() {
    return(commonSpecs);
  }
}

DebugExample.jsp Page that uses the DebugTag custom tag

# DebugExample.jsp Page that uses the DebugTag custom tag

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- 
Illustration of SimplePrimeTag tag. 

Taken from Core Web Programming Java 2 Edition
from Prentice Hall and Sun Microsystems Press,
.
May be freely used or adapted. 
-->
<HTML>
<HEAD>
<TITLE>Using the Debug Tag</TITLE>
<LINK REL=STYLESHEET
      HREF="JSP-Styles.css"
      TYPE="text/css">
</HEAD>
<BODY>
<H1>Using the Debug Tag</H1>
<%@ taglib uri="cwp-taglib.tld" prefix="cwp" %>
Top of regular page. Blah, blah, blah. Yadda, yadda, yadda.
<P>
<cwp:debug>
<B>Debug:</B>
<UL>
  <LI>Current time: <%= new java.util.Date() %>
  <LI>Requesting hostname: <%= request.getRemoteHost() %>
  <LI>Session ID: <%= session.getId() %>
</UL>
</cwp:debug>
<P>
Bottom of regular page. Blah, blah, blah. Yadda, yadda, yadda.
</BODY>
</HTML>

package cwp.tags;

import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.*;
import javax.servlet.*;

/** A tag that includes the body content only if
 *  the "debug" request parameter is set.
 *  <P>
 *  Taken from Core Web Programming Java 2 Edition
 *  from Prentice Hall and Sun Microsystems Press,
 *  .
 *  May be freely used or adapted.
 */

public class DebugTag extends TagSupport {
  public int doStartTag() {
    ServletRequest request = pageContext.getRequest();
    String debugFlag = request.getParameter("debug");
    if ((debugFlag != null) &&
        (!debugFlag.equalsIgnoreCase("false"))) {
      return(EVAL_BODY_INCLUDE);
    } else {
      return(SKIP_BODY);
    }
  }
}

ShearExample.java. Illustrates the effect of applying a shear transformation prior to drawing a square

import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;

/** An example of shear transformations on a rectangle. 
 *
 ***********************

public class ShearExample extends JPanel {
  private static int gap=10, width=100;
  private Rectangle rect = new Rectangle(gap, gap, 100, 100);

  public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D)g;
    for (int i=0; i<5; i++) {
      g2d.setPaint(Color.red);
      g2d.fill(rect);
      // Each new square gets 0.2 more x shear.
      g2d.shear(0.2, 0.0);
      g2d.translate(2*gap + width, 0);
    }
  }

  public static void main(String[] args) {
    String title =
      "Shear: x shear ranges from 0.0 for the leftmost" +
      "'square' to 0.8 for the rightmost one.";
    WindowUtilities.openInJFrame(new ShearExample(),
                                 20*gap + 5*width, 
                                 5*gap + width,
                                 title);
  }
}

LineStyles.java Provides examples of the available styles for joining line segments

import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;

/** A demonstration of different controls when joining two line
 *  segments. The style of the line end point is controlled
 *  through the capStyle parameter.
 *
 ************************************

public class LineStyles extends JPanel {
  private GeneralPath path;
  private static int x = 30, deltaX = 150, y = 300,
                     deltaY = 250, thickness = 40;
  private Circle p1Large, p1Small, p2Large, p2Small,
                 p3Large, p3Small;
  private int compositeType = AlphaComposite.SRC_OVER;
  private AlphaComposite transparentComposite =
    AlphaComposite.getInstance(compositeType, 0.4F);
  private int[] caps =
    { BasicStroke.CAP_SQUARE, BasicStroke.CAP_BUTT,
      BasicStroke.CAP_ROUND };
  private String[] capNames =
    { "CAP_SQUARE", "CAP_BUTT", "CAP_ROUND" };
  private int[] joins =
    { BasicStroke.JOIN_MITER, BasicStroke.JOIN_BEVEL,
      BasicStroke.JOIN_ROUND };
  private String[] joinNames =
    { "JOIN_MITER", "JOIN_BEVEL", "JOIN_ROUND" };

  public LineStyles() {
    path = new GeneralPath();
    path.moveTo(x, y);
    p1Large = new Circle(x, y, thickness/2);
    p1Small = new Circle(x, y, 2);
    path.lineTo(x + deltaX, y - deltaY);
    p2Large = new Circle(x + deltaX, y - deltaY, thickness/2);
    p2Small = new Circle(x + deltaX, y - deltaY, 2);
    path.lineTo(x + 2*deltaX, y);
    p3Large = new Circle(x + 2*deltaX, y, thickness/2);
    p3Small = new Circle(x + 2*deltaX, y, 2);
    setFont(new Font("SansSerif", Font.BOLD, 20));
  }

  public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D)g;
    g2d.setColor(Color.lightGray);
    for(int i=0; i

Illustrates using a local font (Goudy Handtooled BT) to perform drawing in Java 2D

import java.awt.*;

/** An example of using local fonts to perform drawing in
 *  Java 2D.
 *
 **********************

public class FontExample extends GradientPaintExample {
  public FontExample() {
    GraphicsEnvironment env =
      GraphicsEnvironment.getLocalGraphicsEnvironment();
    env.getAvailableFontFamilyNames();
    setFont(new Font("Goudy Handtooled BT", Font.PLAIN, 100));
  }

  protected void drawBigString(Graphics2D g2d) {
    g2d.setPaint(Color.black);
    g2d.drawString("Java 2D", 25, 215);
  }

  public void paintComponent(Graphics g) {
    clear(g);
    Graphics2D g2d = (Graphics2D)g;
    drawGradientCircle(g2d);
    drawBigString(g2d);
  }

  public static void main(String[] args) {
    WindowUtilities.openInJFrame(new FontExample(), 380, 400);
  }
}