You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by ha...@apache.org on 2008/06/09 02:23:04 UTC

svn commit: r664581 - in /myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha: ./ util/

Author: hazems
Date: Sun Jun  8 17:23:03 2008
New Revision: 664581

URL: http://svn.apache.org/viewvc?rev=664581&view=rev
Log:
Moving CAPTCHA classes to Tomahawk.

Added:
    myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/
    myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/AbstractCAPTCHAComponent.java
    myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/CAPTCHARenderer.java
    myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/util/
    myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/util/CAPTCHAConstants.java
    myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/util/CAPTCHAImageGenerator.java
    myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/util/CAPTCHAResponseStream.java
    myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/util/CAPTCHATextGenerator.java
    myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/util/ColorGenerator.java

Added: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/AbstractCAPTCHAComponent.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/AbstractCAPTCHAComponent.java?rev=664581&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/AbstractCAPTCHAComponent.java (added)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/AbstractCAPTCHAComponent.java Sun Jun  8 17:23:03 2008
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.custom.captcha;
+
+import javax.faces.component.UIComponentBase;
+
+/**
+ * 
+ * @JSFComponent
+ *   name = "t:captcha"
+ *   class = "org.apache.myfaces.custom.captcha.CAPTCHAComponent"
+ *   tagClass = "org.apache.myfaces.custom.captcha.CAPTCHATag"
+ * 
+ * @author Hazem Saleh
+ *
+ */
+public abstract class AbstractCAPTCHAComponent extends UIComponentBase {
+
+    public static String COMPONENT_TYPE = "org.apache.myfaces.CAPTCHA";
+    public static String COMPONENT_FAMILY = "org.apache.myfaces.CAPTCHA";
+    public static String DEFAULT_RENDERER_TYPE = "org.apache.myfaces.CAPTCHA";
+    
+    // Value binding constants
+    public static final String ATTRIBUTE_CAPTCHA_SESSION_KEY_NAME = "captchaSessionKeyName";
+    public static final String ATTRIBUTE_IMAGE_WIDTH = "imageWidth";
+    public static final String ATTRIBUTE_IMAGE_HEIGHT = "imageHeight";
+    
+    /**
+     * Determines the CAPTCHA session key name.
+     * 
+     * @JSFProperty
+     * @return
+     */
+    public abstract String getCaptchaSessionKeyName();
+    
+    /**
+     * Integer to indicate the CAPTCHA width. default is 290.
+     * 
+     * @JSFProperty
+     */
+    public abstract String getImageWidth();
+
+    /**
+     * Integer to indicate the CAPTCHA height. default is 81.
+     * 
+     * @JSFProperty
+     */
+    public abstract String getImageHeight();      
+   
+}

Added: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/CAPTCHARenderer.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/CAPTCHARenderer.java?rev=664581&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/CAPTCHARenderer.java (added)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/CAPTCHARenderer.java Sun Jun  8 17:23:03 2008
@@ -0,0 +1,212 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.custom.captcha;
+
+import java.awt.Color;
+import java.io.IOException;
+import java.util.Map;
+
+import javax.faces.FacesException;
+import javax.faces.FactoryFinder;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.context.FacesContextFactory;
+import javax.faces.context.ResponseStream;
+import javax.faces.context.ResponseWriter;
+import javax.faces.lifecycle.Lifecycle;
+import javax.faces.lifecycle.LifecycleFactory;
+import javax.faces.render.Renderer;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.myfaces.component.html.util.HtmlComponentUtils;
+import org.apache.myfaces.component.html.util.ParameterResourceHandler;
+import org.apache.myfaces.custom.captcha.util.CAPTCHAConstants;
+import org.apache.myfaces.custom.captcha.util.CAPTCHAImageGenerator;
+import org.apache.myfaces.custom.captcha.util.CAPTCHAResponseStream;
+import org.apache.myfaces.custom.captcha.util.CAPTCHATextGenerator;
+import org.apache.myfaces.custom.captcha.util.ColorGenerator;
+import org.apache.myfaces.renderkit.html.util.AddResource;
+import org.apache.myfaces.renderkit.html.util.AddResourceFactory;
+import org.apache.myfaces.renderkit.html.util.ResourceLoader;
+
+import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
+/**
+ * 
+ * @JSFRenderer
+ *   renderKitId = "HTML_BASIC" 
+ *   family = "org.apache.myfaces.CAPTCHA"
+ *   type = "org.apache.myfaces.CAPTCHA"
+ *
+ * @author Hazem Saleh
+ *
+ */
+public class CAPTCHARenderer extends Renderer implements ResourceLoader {
+
+    public void encodeBegin(FacesContext context, UIComponent component)
+	    throws IOException {
+
+	CAPTCHAComponent captchaComponent = (CAPTCHAComponent) component;
+
+	generateImageTag(context, captchaComponent);
+    }
+
+    public void encodeEnd(FacesContext context, UIComponent component)
+	    throws IOException {
+	super.encodeEnd(context, component);
+    }
+
+    /*
+     * This helper method is used for generating the img tag that will
+     * use the (AddResource) to generate the url of the generated image.
+     */
+    private void generateImageTag(FacesContext context,
+	    CAPTCHAComponent component) throws IOException {
+
+	AddResource addResource;
+	ResponseWriter writer = context.getResponseWriter();
+	Map params = HtmlComponentUtils.getParameterMap(component);
+	String url;	
+	String captchaSessionKeyName = component.getCaptchaSessionKeyName();
+	String width = component.getImageWidth();
+	String height = component.getImageHeight();
+	
+	// determine width and height of the generated image.
+	if(width == null) 
+	{
+	    width = CAPTCHAConstants.DEFAULT_CAPTCHA_WIDTH + ""; 
+	}
+	
+	if(height == null) 
+	{
+	    height = CAPTCHAConstants.DEFAULT_CAPTCHA_HEIGHT + ""; 
+	}	
+	
+	writer.startElement(HTML.IMG_ELEM, component);
+
+	// constructing the parameter map to be passed to the (AddResource).
+	if (captchaSessionKeyName != null) 
+	{
+	    params.put(CAPTCHAComponent.ATTRIBUTE_CAPTCHA_SESSION_KEY_NAME,
+		    captchaSessionKeyName);
+	}
+	
+	// write the url to trigger the (AddResource).
+	addResource = AddResourceFactory.getInstance(context);
+
+	url = context.getExternalContext().encodeResourceURL(
+		addResource.getResourceUri(context,
+			new ParameterResourceHandler(this.getClass(), params)));
+
+	
+	writer.writeAttribute(HTML.SRC_ATTR, url, null);
+
+	// write rest of attributes.
+	writer.writeAttribute(HTML.WIDTH_ATTR, width, null);
+	
+	writer.writeAttribute(HTML.HEIGHT_ATTR, height, null);	
+	
+	writer.endElement(HTML.IMG_ELEM);
+    }
+
+    /*
+     * This method is implemented to be called from the (AddResource).
+     * It wraps the CAPTCHA image generation.
+     */
+    public void serveResource(ServletContext servletContext,
+	    HttpServletRequest request, HttpServletResponse response,
+	    String resourceUri) throws IOException {
+
+	// get the FacesContext from the ServletContext.
+	FacesContextFactory facesContextFactory = (FacesContextFactory) FactoryFinder
+		.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
+	LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder
+		.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
+	Lifecycle lifecycle = lifecycleFactory.getLifecycle(HtmlComponentUtils
+		.getLifecycleId(servletContext));
+	FacesContext facesContext = facesContextFactory.getFacesContext(
+		servletContext, request, response, lifecycle);
+	facesContext.setResponseStream(new CAPTCHAResponseStream(response
+		.getOutputStream()));
+
+	// render the CAPTCHA.
+	try 
+	{
+	    try 
+	    {
+		renderCAPTCHA(facesContext);
+	    }
+	    catch (IOException e) 
+	    {
+		throw new FacesException("Could not render the CAPTCHA : "
+			+ e.getMessage(), e);
+	    }
+	    facesContext.getResponseStream().close();
+	}
+	finally 
+	{
+	    facesContext.release();
+	}
+    }
+
+    /*
+     * This method is used for rendering the CAPTCHA component.
+     */
+    protected void renderCAPTCHA(FacesContext facesContext) throws IOException {
+
+	// getting CAPTCHA attributes.
+	HttpServletResponse response = (HttpServletResponse) facesContext
+		.getExternalContext().getResponse();
+	ResponseStream out = facesContext.getResponseStream();
+	Map requestMap = facesContext.getExternalContext()
+		.getRequestParameterMap();
+	HttpServletRequest request = (HttpServletRequest) facesContext
+		.getExternalContext().getRequest();
+	String captchaSessionKeyName = requestMap.get(
+		CAPTCHAComponent.ATTRIBUTE_CAPTCHA_SESSION_KEY_NAME).toString();
+	
+	// construct the CAPTCHA image generator object.
+	CAPTCHAImageGenerator captchaImageGenerator = new CAPTCHAImageGenerator();
+	
+	try 
+	{
+	    String captchaText;
+	    Color endingColor = ColorGenerator.generateRandomColor(null);
+	    Color startingColor = ColorGenerator.generateRandomColor(endingColor);
+	    
+	    // Generate random CAPTCHA text.
+	    captchaText = CAPTCHATextGenerator.generateRandomText();	    
+	    
+	    // Generate the image, the BG color is randomized from starting to ending colors.
+            captchaImageGenerator.generateImage(response, captchaText,
+		    startingColor, endingColor);
+
+	    // Set the generated text in the user session.
+	    request.getSession().setAttribute(captchaSessionKeyName,
+		    captchaText);
+
+	}
+	finally 
+	{
+	    out.close();
+	    facesContext.responseComplete();
+	}
+    }
+}

Added: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/util/CAPTCHAConstants.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/util/CAPTCHAConstants.java?rev=664581&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/util/CAPTCHAConstants.java (added)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/util/CAPTCHAConstants.java Sun Jun  8 17:23:03 2008
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.custom.captcha.util;
+
+/**
+ * This interface holds all the CAPTCHA related constants.
+ */
+public interface CAPTCHAConstants {
+	public static final int DEFAULT_CAPTCHA_WIDTH = 290;
+	public static final int DEFAULT_CAPTCHA_HEIGHT = 81;
+	public static final double PI = 3.1415926535897932384626433832795;
+	public static final int TEXT_X_COORDINATE = 50;
+	public static final int TEXT_Y_COORDINATE = 60;
+}

Added: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/util/CAPTCHAImageGenerator.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/util/CAPTCHAImageGenerator.java?rev=664581&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/util/CAPTCHAImageGenerator.java (added)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/util/CAPTCHAImageGenerator.java Sun Jun  8 17:23:03 2008
@@ -0,0 +1,277 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.custom.captcha.util;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.GradientPaint;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.font.TextLayout;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.util.Random;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.batik.ext.awt.image.codec.PNGEncodeParam;
+import org.apache.batik.ext.awt.image.codec.PNGImageEncoder;
+
+
+/**
+ * This class is responsible for generating the CAPTCHA image.
+ */
+public class CAPTCHAImageGenerator {
+
+    //private static final Color startingColor = new Color(150, 50, 150);
+    //private static final Color endingColor = new Color(255, 255, 255);
+
+    /*
+    * A helper method to draw the captcha text on the generated image.
+    */
+    private void drawTextOnImage(Graphics2D graphics, String captchaText) {
+
+	Font font;
+	TextLayout textLayout;
+	double currentFontStatus = Math.random();
+
+	// Generate random font status.
+	if (currentFontStatus >= 0.5) 
+	{
+	    font = new Font("Arial", Font.PLAIN, 60);
+	}
+	else 
+	{
+	    font = new Font("Arial", Font.BOLD, 60);
+	}
+
+	graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+		RenderingHints.VALUE_ANTIALIAS_ON);
+	textLayout = new TextLayout(captchaText, font, graphics
+		.getFontRenderContext());
+
+	textLayout.draw(graphics, CAPTCHAConstants.TEXT_X_COORDINATE,
+		CAPTCHAConstants.TEXT_Y_COORDINATE);
+    }
+
+    /*
+    * A helper method to apply noise on the generated image.
+    */
+    private void applyNoiseOnImage(Graphics2D graphics, int bufferedImageWidth,
+	    int bufferedImageHeight, Color startingColor, Color endingColor) {
+
+	// Applying shear.
+	applyShear(graphics, bufferedImageWidth, bufferedImageHeight,
+		startingColor, endingColor);
+
+	// Drawing a broken line on the image.
+	drawBrokenLineOnImage(graphics);
+    }
+
+    /*
+    * This helper method is used for applying current gradient paint to the
+    * Graphics2D object.
+    */
+    private static void applyCurrentGradientPaint(Graphics2D graphics,
+	    int width, int height, Color startingColor, Color endingColor) {
+
+	GradientPaint gradientPaint = new GradientPaint(0, 0, startingColor,
+		width, height, endingColor);
+
+	graphics.setPaint(gradientPaint);
+    }
+
+    
+    /**
+     * This method generates the CAPTCHA image. 
+     * @param response
+     * @param captchaText
+     * @param startingColor
+     * @param endingColor
+     * @throws IOException
+     */
+    public void generateImage(HttpServletResponse response, String captchaText,
+	    Color startingColor, Color endingColor) throws IOException {
+
+	BufferedImage bufferedImage;
+	Graphics2D graphics;
+	PNGEncodeParam param;
+	PNGImageEncoder captchaPNGImage;
+	
+	// Create the CAPTCHA Image.
+	bufferedImage = new BufferedImage(CAPTCHAConstants.DEFAULT_CAPTCHA_WIDTH, CAPTCHAConstants.DEFAULT_CAPTCHA_HEIGHT,
+		BufferedImage.TYPE_BYTE_INDEXED);
+
+	// Setup the graphics object.
+	graphics = bufferedImage.createGraphics();
+
+	applyCurrentGradientPaint(graphics, bufferedImage.getWidth(),
+		bufferedImage.getHeight(), startingColor, endingColor);
+
+	graphics.fillRect(0, 0, bufferedImage.getWidth(), bufferedImage
+		.getHeight());
+
+	graphics.setColor(Color.black);
+
+	// Draw text on the CAPTCHA image.
+	drawTextOnImage(graphics, captchaText);
+
+	// Apply noise on the CAPTCHA image.
+	applyNoiseOnImage(graphics, bufferedImage.getWidth(), bufferedImage
+		.getHeight(), startingColor, endingColor);
+
+	// Draw the image border.
+	drawBorders(graphics, bufferedImage.getWidth(), bufferedImage
+		.getHeight());
+
+	// Set the reponse content type to jpeg.
+	response.setContentType("image/jpg");
+
+	param = PNGEncodeParam.getDefaultEncodeParam(bufferedImage);
+	captchaPNGImage = new PNGImageEncoder(response.getOutputStream(), param);
+
+	captchaPNGImage.encode(bufferedImage);
+    }
+
+    /*
+    * This helper method is used for drawing a thick line on the image.
+    */
+    private void drawThickLineOnImage(Graphics graphics, int x1, int y1,
+	    int x2, int y2) {
+
+	int dX = x2 - x1;
+	int dY = y2 - y1;
+	int xPoints[] = new int[4];
+	int yPoints[] = new int[4];
+	int thickness = 2;
+
+	double lineLength = Math.sqrt(dX * dX + dY * dY);
+	double scale = (double) (thickness) / (2 * lineLength);
+	double ddx = -scale * (double) dY;
+	double ddy = scale * (double) dX;
+
+	graphics.setColor(Color.black);
+
+	ddx += (ddx > 0) ? 0.5 : -0.5;
+	ddy += (ddy > 0) ? 0.5 : -0.5;
+	dX = (int) ddx;
+	dY = (int) ddy;
+
+	xPoints[0] = x1 + dX;
+	yPoints[0] = y1 + dY;
+	xPoints[1] = x1 - dX;
+	yPoints[1] = y1 - dY;
+	xPoints[2] = x2 - dX;
+	yPoints[2] = y2 - dY;
+	xPoints[3] = x2 + dX;
+	yPoints[3] = y2 + dY;
+
+	graphics.fillPolygon(xPoints, yPoints, 4);
+    }
+
+    /*
+    * This helper method is used for drawing a broken line on the image.
+    */
+    private void drawBrokenLineOnImage(Graphics2D graphics) {
+
+	int yPoint1;
+	int yPoint2;
+	int yPoint3;
+	int yPoint4;
+	int yPoint5;
+	Random random = new Random();
+
+	// Random Y Points.
+	yPoint1 = random.nextInt(CAPTCHAConstants.DEFAULT_CAPTCHA_HEIGHT);
+	yPoint2 = random.nextInt(CAPTCHAConstants.DEFAULT_CAPTCHA_HEIGHT);
+	yPoint3 = CAPTCHAConstants.DEFAULT_CAPTCHA_HEIGHT / 2;
+	yPoint4 = random.nextInt(CAPTCHAConstants.DEFAULT_CAPTCHA_HEIGHT);
+	yPoint5 = random.nextInt(CAPTCHAConstants.DEFAULT_CAPTCHA_HEIGHT);
+
+	// Draw the random broken line.
+	drawThickLineOnImage(graphics, 0, yPoint1,
+		CAPTCHAConstants.DEFAULT_CAPTCHA_WIDTH / 4, yPoint2);
+	drawThickLineOnImage(graphics,
+		CAPTCHAConstants.DEFAULT_CAPTCHA_WIDTH / 4, yPoint2,
+		CAPTCHAConstants.DEFAULT_CAPTCHA_WIDTH / 2, yPoint3);
+	drawThickLineOnImage(graphics,
+		CAPTCHAConstants.DEFAULT_CAPTCHA_WIDTH / 2, yPoint3,
+		3 * CAPTCHAConstants.DEFAULT_CAPTCHA_WIDTH / 4, yPoint4);
+	drawThickLineOnImage(graphics,
+		3 * CAPTCHAConstants.DEFAULT_CAPTCHA_WIDTH / 4, yPoint4,
+		CAPTCHAConstants.DEFAULT_CAPTCHA_WIDTH, yPoint5);
+    }
+
+    /*
+    * This helper method is used for calculating the delta of the shearing
+    * equation.
+    */
+    private double getDelta(int period, double i, double phase, double frames) {
+	return (double) (period / 2)
+		* Math.sin(i / (double) period
+			+ (2 * CAPTCHAConstants.PI * phase) / frames);
+    }
+
+    /*
+    * This helper method is used for applying shear on the image.
+    */
+    private void applyShear(Graphics2D graphics, int bufferedImageWidth,
+	    int bufferedImageHeight, Color startingColor, Color endingColor) {
+
+	int periodValue = 20;
+	int numberOfFrames = 15;
+	int phaseNumber = 7;
+	double deltaX;
+	double deltaY;
+
+	applyCurrentGradientPaint(graphics, bufferedImageWidth,
+		bufferedImageHeight, startingColor, endingColor);
+
+	for (int i = 0; i < bufferedImageWidth; ++i) 
+	{
+	    deltaX = getDelta(periodValue, i, phaseNumber, numberOfFrames);
+	    graphics.copyArea(i, 0, 1, bufferedImageHeight, 0, (int) deltaX);
+	    graphics.drawLine(i, (int) deltaX, i, 0);
+	    graphics.drawLine(i, (int) deltaX + bufferedImageHeight, i,
+		    bufferedImageHeight);
+	}
+
+	for (int i = 0; i < bufferedImageHeight; ++i) 
+	{
+	    deltaY = getDelta(periodValue, i, phaseNumber, numberOfFrames);
+	    graphics.copyArea(0, i, bufferedImageWidth, 1, (int) deltaY, 0);
+	    graphics.drawLine((int) deltaY, i, 0, i);
+	    graphics.drawLine((int) deltaY + bufferedImageWidth, i,
+		    bufferedImageWidth, i);
+	}
+    }
+
+    /*
+    * This helper method is used for drawing the borders the image.
+    */
+    private void drawBorders(Graphics2D graphics, int width, int height) {
+	graphics.setColor(Color.black);
+
+	graphics.drawLine(0, 0, 0, width - 1);
+	graphics.drawLine(0, 0, width - 1, 0);
+	graphics.drawLine(0, height - 1, width, height - 1);
+	graphics.drawLine(width - 1, height - 1, width - 1, 0);
+    }
+
+}

Added: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/util/CAPTCHAResponseStream.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/util/CAPTCHAResponseStream.java?rev=664581&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/util/CAPTCHAResponseStream.java (added)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/util/CAPTCHAResponseStream.java Sun Jun  8 17:23:03 2008
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.custom.captcha.util;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import javax.faces.context.ResponseStream;
+
+/**
+ * This class is responsible for wrapping the CAPTCHA Image
+ * response stream.
+ */
+public final class CAPTCHAResponseStream extends ResponseStream {
+	private final OutputStream _out;
+
+	public CAPTCHAResponseStream(OutputStream out) {
+		_out = out;
+	}
+
+	public void close() throws IOException {
+		_out.flush();
+		_out.close();
+	}
+
+	public void flush() throws IOException {
+		_out.flush();
+	}
+
+	public void write(byte[] b, int off, int len) throws IOException {
+		_out.write(b, off, len);
+	}
+
+	public void write(byte[] b) throws IOException {
+		_out.write(b);
+	}
+
+	public void write(int b) throws IOException {
+		_out.write(b);
+	}
+}

Added: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/util/CAPTCHATextGenerator.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/util/CAPTCHATextGenerator.java?rev=664581&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/util/CAPTCHATextGenerator.java (added)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/util/CAPTCHATextGenerator.java Sun Jun  8 17:23:03 2008
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.custom.captcha.util;
+
+import java.util.Random;
+
+/**
+ * This class is responsible for generating the 
+ * CAPTCHA text.
+ */
+public class CAPTCHATextGenerator {
+	
+	/* CAPTCHA possible characters */
+	private final static char[] CAPTCHA_POSSIBLE_CHARS = new char[] { 'a', 'b',
+			'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+			'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '1', '2',
+			'3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
+			'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
+			'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
+	
+	/**
+	 * generateRandomText() generates the CAPTCHA text
+	 * @return the random generated text. 
+	 */
+	public static String generateRandomText() {
+		
+		int totalPossibleCharacters = CAPTCHA_POSSIBLE_CHARS.length - 1;	
+		String captchaText = "";
+		Random random = new Random();
+		int captchaTextLength = 5;
+		int randomNumber = random.nextInt(10);
+		
+		// Determine the CAPTCHA Length whether it is five or six.
+		if(randomNumber >= 5) {
+			captchaTextLength = 6;
+		}
+		
+		// Generate the random String.
+		for (int i = 0; i < captchaTextLength; ++i) {
+			captchaText += CAPTCHA_POSSIBLE_CHARS[random
+					.nextInt(totalPossibleCharacters) + 1];
+		}
+		
+		return captchaText;
+	}
+	
+}

Added: myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/util/ColorGenerator.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/util/ColorGenerator.java?rev=664581&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/util/ColorGenerator.java (added)
+++ myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/custom/captcha/util/ColorGenerator.java Sun Jun  8 17:23:03 2008
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.custom.captcha.util;
+
+import java.awt.Color;
+
+/**
+ * This class is responsible for generating CAPTCHA random color...
+ */
+public class ColorGenerator {
+    
+    private final static int COLOR_DEGREES = 255;
+    private final static int COLOR_GENERATOR_DELTA = 127;       
+    
+    /**
+     * This method is used for generating a random color.
+     * @param startFrom -> the color that we should be away from.
+     * @return the new color.
+     */
+    public static Color generateRandomColor(Color startFrom) {
+	
+	/* if the startingFrom color is null, then generate a new random color. */
+	if (startFrom == null) 
+	{
+	    return new Color((int) (Math.random() * COLOR_DEGREES), (int) (Math
+		    .random() * COLOR_DEGREES),
+		    (int) (Math.random() * COLOR_DEGREES));
+	}
+
+	/* try to avoid the startFrom color. */
+	int startingRed = (startFrom.getRed() >= 128) ? 0 : 128;
+	int startingGreen = (startFrom.getGreen() >= 128) ? 0 : 128;
+	int startingBlue = (startFrom.getBlue() >= 128) ? 0 : 128;	
+	
+	// generate the new random colors.  
+	int newRandomRed = (int) (Math.random() * (startingRed + COLOR_GENERATOR_DELTA));
+	int newRandomGreen = (int) (Math.random() * (startingGreen + COLOR_GENERATOR_DELTA));
+	int newRandomBlue = (int) (Math.random() * (startingBlue + COLOR_GENERATOR_DELTA));
+	
+	/* 
+	 * If the newly generated color is less than the starting color 
+	 * then add the starting color to it. 
+	 */
+	if (newRandomRed < startingRed) 
+	{
+	    newRandomRed += startingRed;
+	}
+
+	if (newRandomGreen < startingGreen) 
+	{
+	    newRandomGreen += startingGreen;
+	}
+	
+	if (newRandomBlue < startingBlue) 
+	{
+	    newRandomBlue += startingBlue;
+	}	
+
+	return new Color(newRandomRed, newRandomGreen, newRandomBlue);
+    }
+}