1
2
3
4
5
6
7 package com.octo.captcha.image;
8
9 import com.octo.captcha.Captcha;
10
11
12 import javax.imageio.ImageIO;
13 import javax.imageio.stream.MemoryCacheImageInputStream;
14 import javax.imageio.stream.MemoryCacheImageOutputStream;
15 import java.awt.image.BufferedImage;
16 import java.io.IOException;
17
18 /***
19 * <p>String question about a BufferedImage challenge. Abstract.</p>
20 *
21 * @author <a href="mailto:mag@jcaptcha.net">Marc-Antoine Garrigue</a>
22 * @version 1.0
23 */
24 public abstract class ImageCaptcha implements Captcha {
25
26 private Boolean hasChallengeBeenCalled = Boolean.FALSE;
27
28 protected String question;
29
30 protected transient BufferedImage challenge;
31
32 protected ImageCaptcha(String question, BufferedImage challenge) {
33 this.challenge = challenge;
34 this.question = question;
35 }
36
37 /***
38 * Accessor captcha question
39 *
40 * @return the question
41 */
42 public final String getQuestion() {
43 return question;
44 }
45
46 /***
47 * @return the challenge
48 */
49 public final Object getChallenge() {
50 return getImageChallenge();
51 }
52
53 /***
54 * @return the image challenge
55 */
56 public final BufferedImage getImageChallenge() {
57 hasChallengeBeenCalled = Boolean.TRUE;
58 return challenge;
59 }
60
61
62 /***
63 * Dispose the challenge, once this method is call the getChallenge method will return null.<br> It has been added
64 * for technical reasons : a captcha is always used in a two step fashion<br> First submit the challenge, and then
65 * wait until the response arrives.<br> It had been asked to have a method to dispose the challenge that is no
66 * longer used after being dipslayed. So here it is!
67 */
68 public final void disposeChallenge() {
69 this.challenge = null;
70 }
71
72 /***
73 * This method should return true if the getChalenge method has been called (has been added in order to properly
74 * manage the captcha state.
75 *
76 * @return true if getChallenge has been called false otherwise.
77 */
78 public Boolean hasGetChalengeBeenCalled() {
79 return hasChallengeBeenCalled;
80 }
81
82 /***
83 * This method have to be implemented in order to serialize the image challenge to JPEG format
84 * @param out The target outputStream in which the captcha will be serialized
85 * @throws IOException
86 */
87 private void writeObject(java.io.ObjectOutputStream out)
88 throws IOException {
89
90
91 out.defaultWriteObject();
92
93
94 if (this.challenge != null) {
95
96 ImageIO.write(this.challenge, "png", new MemoryCacheImageOutputStream(out));
97 }
98 }
99
100 /***
101 * This method have to be implemented in order to unserialize the image challenge from JPEG format
102 * @param in The source inputStream from which the captcha will be unserialized
103 * @throws IOException
104 * @throws ClassNotFoundException
105 */
106 private void readObject(java.io.ObjectInputStream in)
107 throws IOException, ClassNotFoundException {
108
109
110 in.defaultReadObject();
111
112 try {
113
114 this.challenge =ImageIO.read(new MemoryCacheImageInputStream(in));
115 } catch (IOException e) {
116 if (!hasChallengeBeenCalled.booleanValue()) {
117
118
119 throw e;
120 }
121 }
122 }
123 }