Java tutorial
/* * Apache License * Version 2.0, January 2004 * http://www.apache.org/licenses/ * * Copyright 2008-2010 by chenillekit.org * * Licensed 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 */ package org.chenillekit.tapestry.core.components; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import javax.imageio.ImageIO; import org.apache.commons.codec.DecoderException; import org.apache.commons.codec.EncoderException; import org.apache.commons.codec.net.BCodec; import org.apache.tapestry5.BindingConstants; import org.apache.tapestry5.ComponentResources; import org.apache.tapestry5.Link; import org.apache.tapestry5.MarkupWriter; import org.apache.tapestry5.StreamResponse; import org.apache.tapestry5.annotations.OnEvent; import org.apache.tapestry5.annotations.Parameter; import org.apache.tapestry5.annotations.Persist; import org.apache.tapestry5.corelib.base.AbstractField; import org.apache.tapestry5.ioc.annotations.Inject; import org.apache.tapestry5.services.Request; import org.chenillekit.image.services.CaptchaProducer; import org.chenillekit.tapestry.core.utils.JPEGInline; /** * A Captcha is a type of challenge-response test used in computing to ensure that the response is not generated by a computer. * The process usually involves one computer (a server) asking a user to complete a simple test which the computer is able to * generate and grade. Because other computers are unable to solve the CAPTCHA, any user entering a correct solution is presumed * to be human. Thus, it is sometimes described as a reverse Turing test, because it is administered by a machine and targeted to * a human, in contrast to the standard Turing test that is typically administered by a human and targeted to a machine. A common * type of CAPTCHA requires that the user type letters or digits from a distorted image that appears on the screen. * <p/> * This component based on <a href="http://code.google.com/p/kaptcha/">kaptcha library</a> and produce following HTML code: * <p/> * <pre> * <span id="kaptcha1" class="ck-kaptcha"> * <img id="kaptcha1_kaptcha" class="ck-kaptcha" src="..."/> * <input id="kaptcha1_input" class="ck-kaptcha" type="text" name="kaptcha1"/> * </span> * </pre> * <p/> * so you can change the design by cascading style sheets by the "ck-kaptcha" class. * <br/> * To use this component, you need the <a href="http://www.chenillekit.org/chenillekit-image/index.html">chenillekit-image library</a> in you classpath. * * @version $Id$ */ public class Kaptcha extends AbstractField { private static final String EVENT_NAME = "kaptchaEvent"; @Parameter(required = true, defaultPrefix = BindingConstants.PROP) private boolean value; @Persist private String kaptchaValue; private String textFieldValue; /** * ComponentResources. For blocks, messages, crete actionlink, trigger event */ @Inject private ComponentResources resources; /** * Request object for information on current request */ @Inject private Request request; @Inject private CaptchaProducer kaptchaProducer; /** * Tapestry render phase method. * Start a tag here, end it in afterRender */ void beginRender(MarkupWriter writer) { writer.element("span", "id", getClientId(), "class", "ck-kaptcha"); writer.element("img", "id", String.format("%s_kaptcha", getClientId()), "src", getImageLink(), "class", "ck-kaptcha"); writer.end(); // img // <input t:id="textField" type="text" class="ck-kaptcha-input"/> writer.element("input", "id", String.format("%s_input", getClientId()), "type", "text", "name", getControlName(), "value", textFieldValue, "class", "ck-kaptcha"); writer.end(); // input } /** * Tapestry render phase method. End a tag here. */ void afterRender(MarkupWriter writer) { writer.end(); // span } private Link getImageLink() { BCodec bCodec = new BCodec(); try { return resources.createEventLink(EVENT_NAME, bCodec.encode(kaptchaProducer.createText())); } catch (EncoderException e) { throw new RuntimeException(e); } } @OnEvent(value = EVENT_NAME) public StreamResponse onKaptchaImage(String kaptchaValue) { BCodec bCodec = new BCodec(); try { this.kaptchaValue = bCodec.decode(kaptchaValue); } catch (DecoderException e) { throw new RuntimeException(e); } BufferedImage kapatchImage = kaptchaProducer.createImage(this.kaptchaValue); try { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ImageIO.write(kapatchImage, "jpg", byteArrayOutputStream); ByteArrayInputStream bais = new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); return new JPEGInline(bais, (String[]) null); } catch (IOException e) { throw new RuntimeException(e); } } /** * Method implemented by subclasses to actually do the work of processing the submission of the form. The element's * elementName property will already have been set. This method is only invoked if the field is <strong>not {@link * #isDisabled() disabled}</strong>. * * @param elementName the name of the element (used to find the correct parameter in the request) */ protected void processSubmission(String elementName) { String rawValue = request.getParameter(elementName); value = this.kaptchaValue.equals(rawValue); } }