1
2
3
4
5
6
7 package com.octo.captcha.component.image.backgroundgenerator;
8
9 import com.octo.captcha.CaptchaException;
10
11 import javax.imageio.ImageIO;
12 import java.awt.*;
13 import java.awt.image.BufferedImage;
14 import java.io.File;
15 import java.io.FileInputStream;
16 import java.io.IOException;
17 import java.io.UnsupportedEncodingException;
18 import java.net.URL;
19 import java.net.URLDecoder;
20
21 import java.util.*;
22 import java.util.List;
23
24 /***
25 * <p>File reader background generator that return a random image from the ones found in the directory </p>
26 * <p>You can place images in the classpath directory, in this case take care to use a unique directory name (not already contained in a jar file)</p>
27 *
28 * @author <a href="mailto:mag@octo.com">Marc-Antoine Garrigue</a>
29 * @version 1.0
30 */
31 public class FileReaderRandomBackgroundGenerator extends
32 AbstractBackgroundGenerator {
33
34 private List images = new ArrayList();
35 private String rootPath = ".";
36
37 public FileReaderRandomBackgroundGenerator(Integer width,
38 Integer height, String rootPath) {
39 super(width, height);
40
41 if (rootPath != null)
42 this.rootPath = rootPath;
43
44 File dir = findDirectory(this.rootPath);
45
46 File[] files = dir.listFiles();
47
48
49 if (files != null) {
50 for (File file : files) {
51 BufferedImage out = null;
52 if (file.isFile()) {
53 out = getImage(file);
54 }
55 if (out != null) {
56 images.add(images.size(), out);
57 }
58 }
59
60
61 if (images.size() != 0) {
62 for (int i = 0; i < images.size(); i++) {
63 BufferedImage bufferedImage = (BufferedImage) images.get(i);
64 images.set(i, tile(bufferedImage));
65 }
66 } else {
67 throw new CaptchaException("Root path directory is valid but " +
68 "does not contains any image (jpg) files");
69 }
70 }
71 }
72
73 /***
74 *
75 */
76 protected static final Map cachedDirectories = new HashMap();
77
78 protected File findDirectory(String rootPath) {
79 if (cachedDirectories.containsKey(rootPath)) {
80 return (File) cachedDirectories.get(rootPath);
81 }
82
83
84 File dir = new File(rootPath);
85 StringBuffer triedPath = new StringBuffer();
86 appendFilePath(triedPath, dir);
87 if (isNotReadable(dir)) {
88
89 dir = new File(".", rootPath);
90 appendFilePath(triedPath, dir);
91 if (isNotReadable(dir)) {
92
93 dir = new File("/", rootPath);
94 appendFilePath(triedPath, dir);
95
96 if (isNotReadable(dir)) {
97
98 URL url = FileReaderRandomBackgroundGenerator.class.getClassLoader().getResource(rootPath);
99 if (url != null) {
100 dir = new File(getFilePath(url));
101 appendFilePath(triedPath, dir);
102
103 } else {
104
105 url = ClassLoader.getSystemClassLoader().getResource(rootPath);
106
107 if (url != null) {
108 dir = new File(getFilePath(url));
109 appendFilePath(triedPath, dir);
110
111 }
112 }
113 }
114 }
115 }
116
117 if (isNotReadable(dir)) {
118
119 StringTokenizer token = getClasspathFromSystemProperty();
120 while (token.hasMoreElements()) {
121 String path = token.nextToken();
122 if (!path.endsWith(".jar")) {
123 dir = new File(path, rootPath);
124 appendFilePath(triedPath, dir);
125 if (dir.canRead() && dir.isDirectory()) {
126 break;
127 }
128 }
129 }
130 }
131
132
133 if (isNotReadable(dir)) {
134 throw new CaptchaException("All tried paths :'" + triedPath.toString() + "' is not" +
135 " a directory or cannot be read");
136 }
137
138
139 cachedDirectories.put(rootPath, dir);
140
141 return dir;
142 }
143
144 private String getFilePath(URL url) {
145 String file = null;
146 try {
147 file = URLDecoder.decode(url.getFile(), "UTF-8");
148 } catch (UnsupportedEncodingException e) {
149
150 }
151 return file;
152 }
153
154
155
156 private boolean isNotReadable(File dir) {
157 return !dir.canRead() || !dir.isDirectory();
158 }
159
160 private StringTokenizer getClasspathFromSystemProperty() {
161
162 String classpath = System.getProperty("java.class.path");
163 return new StringTokenizer(classpath, File.pathSeparator);
164 }
165
166
167 private void appendFilePath(StringBuffer triedPath, File dir) {
168 triedPath.append(dir.getAbsolutePath());
169 triedPath.append("\n");
170 }
171
172 private BufferedImage tile(BufferedImage tileImage) {
173 BufferedImage image = new BufferedImage(getImageWidth(),
174 getImageHeight(), tileImage.getType());
175 Graphics2D g2 = (Graphics2D) image.getGraphics();
176 int NumberX = (getImageWidth() / tileImage.getWidth());
177 int NumberY = (getImageHeight() / tileImage.getHeight());
178 for (int k = 0; k <= NumberY; k++) {
179 for (int l = 0; l <= NumberX; l++) {
180 g2.drawImage(tileImage, l * tileImage.getWidth(), k *
181 tileImage.getHeight(),
182 Math.min(tileImage.getWidth(), getImageWidth()),
183 Math.min(tileImage.getHeight(), getImageHeight()),
184 null);
185 }
186 }
187 g2.dispose();
188 return image;
189 }
190
191 private static BufferedImage getImage(File o) {
192
193 try {
194 FileInputStream fis = new FileInputStream(o);
195 BufferedImage out =ImageIO.read(fis);
196 fis.close();
197
198
199 return out;
200
201 } catch (IOException e) {
202 throw new CaptchaException("Unknown error during file reading ", e);
203 }
204 }
205
206 /***
207 * Generates a backround image on wich text will be paste. Implementations must take into account the imageHeigt and
208 * imageWidth.
209 *
210 * @return the background image
211 */
212 public BufferedImage getBackground() {
213 return (BufferedImage) images.get(myRandom.nextInt(images.size()));
214 }
215
216 }