/* * JCaptcha, the open source java framework for captcha definition and integration * Copyright (c) 2007 jcaptcha.net. All Rights Reserved. * See the LICENSE.txt file distributed with this package. */ package com.octo.captcha.image; import com.octo.captcha.Captcha; import javax.imageio.ImageIO; import javax.imageio.stream.MemoryCacheImageInputStream; import javax.imageio.stream.MemoryCacheImageOutputStream; import java.awt.image.BufferedImage; import java.io.IOException; /** * <p>String question about a BufferedImage challenge. Abstract.</p> * * @author <a href="mailto:mag@jcaptcha.net">Marc-Antoine Garrigue</a> * @version 1.0 */ public abstract class ImageCaptcha implements Captcha { private Boolean hasChallengeBeenCalled = Boolean.FALSE; protected String question; protected transient BufferedImage challenge; protected ImageCaptcha(String question, BufferedImage challenge) { this.challenge = challenge; this.question = question; } /** * Accessor captcha question * * @return the question */ public final String getQuestion() { return question; } /** * @return the challenge */ public final Object getChallenge() { return getImageChallenge(); } /** * @return the image challenge */ public final BufferedImage getImageChallenge() { hasChallengeBeenCalled = Boolean.TRUE; return challenge; } /** * Dispose the challenge, once this method is call the getChallenge method will return null.<br> It has been added * for technical reasons : a captcha is always used in a two step fashion<br> First submit the challenge, and then * wait until the response arrives.<br> It had been asked to have a method to dispose the challenge that is no * longer used after being dipslayed. So here it is! */ public final void disposeChallenge() { this.challenge = null; } /** * This method should return true if the getChalenge method has been called (has been added in order to properly * manage the captcha state. * * @return true if getChallenge has been called false otherwise. */ public Boolean hasGetChalengeBeenCalled() { return hasChallengeBeenCalled; } /** * This method have to be implemented in order to serialize the image challenge to JPEG format * @param out The target outputStream in which the captcha will be serialized * @throws IOException */ private void writeObject(java.io.ObjectOutputStream out) throws IOException { // Serialize captcha fields with defaut method out.defaultWriteObject(); // If the challenge has not been disposed if (this.challenge != null) { // use png encoding ImageIO.write(this.challenge, "png", new MemoryCacheImageOutputStream(out)); } } /** * This method have to be implemented in order to unserialize the image challenge from JPEG format * @param in The source inputStream from which the captcha will be unserialized * @throws IOException * @throws ClassNotFoundException */ private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { // UnSerialize captcha fields with default method in.defaultReadObject(); try { this.challenge =ImageIO.read(new MemoryCacheImageInputStream(in)); } catch (IOException e) { if (!hasChallengeBeenCalled.booleanValue()) { // If the getChallenge method has not been called the challenge should be available for unmarhslling. // In this case, the thrown Exception is not related to the dispose status throw e; } } } }