1 package org.jmage.resource;
2
3 import org.apache.log4j.Logger;
4 import org.apache.log4j.Priority;
5 import org.jmage.ApplicationContext;
6
7 import javax.servlet.ServletContext;
8 import java.awt.*;
9 import java.io.*;
10 import java.net.MalformedURLException;
11 import java.net.URI;
12 import java.net.URL;
13 import java.net.URLConnection;
14 import java.util.ArrayList;
15 import java.util.List;
16 import java.util.Properties;
17
18 /***
19 * FontFactory loads and creates fonts as resources from system environment.
20 */
21 public class FontFactory implements ResourceFactory {
22 protected static FontFactory fontFactory;
23
24 private final static String TTF = "ttf";
25
26 private final static String HTTP = "http";
27 private final static String FILE = "file";
28
29 private static final char SUFFIX_SEPARATOR = '.';
30
31 protected static Logger log = Logger.getLogger(FontFactory.class.getName());
32 protected List fontTypes;
33 protected List schemeTypes;
34 protected ApplicationContext applicationContext;
35 protected ServletContext servletContext;
36
37 private static final String resourcedir = "resourcedir";
38 private static final String FONTS = "fonts";
39 private static final String SERVLET_CONTEXT = "SERVLET_CONTEXT";
40 private static final String URI_HANDLINGERROR = "unable to handle URI resource, cause: ";
41 private static final String FILE_RESOURCE_RETRIEVED = " retrieved file resource: ";
42 private static final String URL_RESOURCE_RETRIEVED = " retrieved URL resource: ";
43 private static final String SCHEME_ERROR = "unable to retrieve resource, could not handle scheme: ";
44 private static final String FILE_LOADED = " loaded font from file: ";
45 private static final String FILE_LOADERROR = "unable to load font from file: ";
46 private static final String SERVLET_LOAD = " loaded font from servlet container: ";
47 private static final String SERVLET_LOADERROR = "unable to load font from servlet container: ";
48 private static final String URL_LOADERROR = "unable to load font from URL: ";
49 private static final String URL_LOADED = " loaded font from url: ";
50 private static final String CAUSE = ", cause: ";
51 private static final String SLASH = "/";
52 private static final String REGEX_BACKSLASH = "////";
53 private static final String CLASSPATH_LOADERROR = "unable to retrieve font from classpath, cause: ";
54
55 public FontFactory() {
56 fontTypes = new ArrayList();
57 fontTypes.add(TTF);
58
59 schemeTypes = new ArrayList();
60 schemeTypes.add(HTTP);
61 schemeTypes.add(FILE);
62 }
63
64 public void configureRequestProperties(Properties properties) {
65
66 }
67
68 public void removeRequestProperties(Properties properties) {
69
70 }
71
72 public void configure(ApplicationContext context) {
73 this.applicationContext = context;
74 this.servletContext = (ServletContext) this.applicationContext.get(SERVLET_CONTEXT);
75 }
76
77 public boolean canHandle(URI resource) {
78 try {
79 String suffix = resource.getPath().substring(resource.getPath().lastIndexOf(SUFFIX_SEPARATOR) + 1).toLowerCase();
80 String scheme = resource.getScheme();
81 return fontTypes.contains(suffix) && schemeTypes.contains(scheme);
82 } catch (Exception e) {
83 if (log.isInfoEnabled()) log.info(URI_HANDLINGERROR + e.getMessage());
84 return false;
85 }
86 }
87
88 public Object createFrom(URI resource) throws ResourceException {
89 String scheme = resource.getScheme().toLowerCase();
90 if (FILE.equals(scheme)) {
91 File file = new File(resource);
92 Font font = this.getFile(file);
93 if (log.isInfoEnabled()) log.info(FILE_RESOURCE_RETRIEVED + file.getPath());
94 return font;
95 }
96 if (HTTP.equals(scheme)) {
97 URL url = null;
98 try {
99 url = resource.toURL();
100 } catch (MalformedURLException e) {
101 throw new ResourceException(e.getMessage());
102 }
103 Font font = this.getURL(url);
104 if (log.isInfoEnabled()) log.info(URL_RESOURCE_RETRIEVED + url.toString());
105 return font;
106 }
107 throw new ResourceException(SCHEME_ERROR + scheme);
108 }
109
110 protected Font getFile(File file) throws ResourceException {
111 Font font = null;
112
113
114 font = font == null ? this.getAbsoluteFile(file) : font;
115
116
117 font = font == null ? this.getServletContainerResource(file) : font;
118
119
120 font = font == null ? this.getJMAGEResourceDirFile(file) : font;
121
122
123 font = font == null ? this.getClassPathResource(file) : font;
124
125
126 font = font == null ? this.getCurrentDirFile(file) : font;
127
128
129 if (font == null) {
130 if (log.isEnabledFor(Priority.ERROR)) log.error(FILE_LOADERROR + file);
131 throw new ResourceException(FILE_LOADERROR + file);
132 }
133 return font;
134 }
135
136 protected Font getClassPathResource(File file) throws ResourceException {
137 Font font = null;
138 String fontPath = file.getPath();
139
140 if (fontPath.indexOf(File.separator) == 0) {
141 fontPath = fontPath.substring(1);
142 }
143
144 ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
145 URL fontURL = classLoader.getResource(fontPath);
146 if (fontURL == null) {
147 fontURL = classLoader.getResource(SLASH + fontPath);
148 if (fontURL != null) {
149 fontPath = (SLASH + fontPath);
150 }
151 }
152 if (fontURL == null) {
153 fontURL = classLoader.getResource(FONTS + SLASH + fontPath);
154 if (fontURL != null) {
155 fontPath = (FONTS + SLASH + fontPath);
156 }
157 }
158 if (fontURL == null) {
159 fontURL = classLoader.getResource(SLASH + FONTS + SLASH + fontPath);
160 if (fontURL != null) {
161 fontPath = (SLASH + FONTS + SLASH + fontPath);
162 }
163 }
164
165 if (fontURL == null) {
166 classLoader = this.getClass().getClassLoader();
167 fontURL = classLoader.getResource(SLASH + fontPath);
168 if (fontURL != null) {
169 fontPath = (SLASH + fontPath);
170 }
171 }
172 if (fontURL == null) {
173 classLoader = this.getClass().getClassLoader();
174 fontURL = classLoader.getResource(FONTS + SLASH + fontPath);
175 if (fontURL != null) {
176 fontPath = (FONTS + SLASH + fontPath);
177 }
178 }
179 if (fontURL == null) {
180 classLoader = this.getClass().getClassLoader();
181 fontURL = classLoader.getResource(SLASH + FONTS + SLASH + fontPath);
182 if (fontURL != null) {
183 fontPath = (SLASH + FONTS + SLASH + fontPath);
184 }
185 }
186
187 if (fontURL != null) {
188 try {
189 font = Font.createFont(Font.TRUETYPE_FONT, classLoader.getResourceAsStream(fontPath));
190 } catch (Exception e) {
191 if (log.isEnabledFor(Priority.INFO)) log.info(CLASSPATH_LOADERROR + e.getMessage());
192 }
193 }
194 return font;
195 }
196
197 protected Font getCurrentDirFile(File file) {
198 Font font = null;
199 if (font == null) {
200 File current = new File(".");
201 File fontFile = new File(current, file.getPath());
202 if (fontFile.isFile() && fontFile.exists()) {
203 try {
204 font = Font.createFont(Font.TRUETYPE_FONT, this.loadFile(fontFile));
205 if (log.isDebugEnabled()) log.debug(FILE_LOADED + file.getPath());
206 } catch (Exception e) {
207 if (log.isEnabledFor(Priority.ERROR)) log.error(FILE_LOADERROR, e);
208 }
209 }
210 }
211 return font;
212 }
213
214 protected Font getJMAGEResourceDirFile(File file) {
215 Font font = null;
216 String resourceDirName = this.applicationContext.getProperty(resourcedir);
217
218 if (resourceDirName == null) {
219 return null;
220 }
221 File fontResourceDir = new File(resourceDirName, FONTS);
222 if (fontResourceDir != null && fontResourceDir.isDirectory() && fontResourceDir.exists()) {
223 File fontFile = new File(fontResourceDir, file.getPath());
224 if (fontFile.isFile() && fontFile.exists()) {
225 try {
226 font = Font.createFont(Font.TRUETYPE_FONT, this.loadFile(fontFile));
227 if (log.isDebugEnabled()) log.debug(FILE_LOADED + file.getPath());
228 } catch (Exception e) {
229 if (log.isEnabledFor(Priority.ERROR)) log.error(FILE_LOADERROR + file.getAbsolutePath(), e);
230 }
231 }
232 }
233 return font;
234 }
235
236 protected Font getAbsoluteFile(File file) {
237 Font font = null;
238 if (font == null && file.isAbsolute() && file.exists()) {
239 try {
240 font = Font.createFont(Font.TRUETYPE_FONT, this.loadFile(file));
241 if (log.isDebugEnabled()) log.debug(FILE_LOADED + file.getAbsolutePath());
242 } catch (Exception e) {
243 if (log.isEnabledFor(Priority.ERROR)) log.error(FILE_LOADERROR, e);
244 }
245 }
246 return font;
247 }
248
249 protected Font getURL(URL url) throws ResourceException {
250 Font font = null;
251 String errorMessage = URL_LOADERROR + url.toString();
252 try {
253 font = Font.createFont(Font.TRUETYPE_FONT, this.loadUrl(url));
254 if (log.isDebugEnabled()) log.debug(URL_LOADED + url.toString());
255 } catch (Exception e) {
256 if (log.isEnabledFor(Priority.ERROR)) log.error(errorMessage + CAUSE + e.getMessage());
257 throw new ResourceException(errorMessage + CAUSE + e.getMessage());
258 }
259
260
261 if (font == null) {
262 if (log.isEnabledFor(Priority.ERROR)) log.error(errorMessage);
263 throw new ResourceException(errorMessage);
264 }
265 return font;
266 }
267
268 /***
269 * Get the file from the ServletContainer as a system resource.
270 *
271 * @param file the file
272 * @return the image
273 */
274 protected Font getServletContainerResource(File file) {
275 Font font = null;
276
277
278 if (servletContext == null) {
279 servletContext = (ServletContext) this.applicationContext.get(SERVLET_CONTEXT);
280 }
281
282 if(servletContext != null) {
283 try {
284 InputStream is = servletContext.getResourceAsStream(file.getPath().replaceAll(REGEX_BACKSLASH, SLASH));
285
286
287 if (is == null) {
288 File derived = new File(SLASH + FONTS, file.getPath());
289 is = servletContext.getResourceAsStream(derived.getPath().replaceAll(REGEX_BACKSLASH, SLASH));
290 }
291 if (is == null) {
292 File derived = new File(FONTS, file.getPath());
293 is = servletContext.getResourceAsStream(derived.getPath().replaceAll(REGEX_BACKSLASH, SLASH));
294 }
295 if (is == null) {
296 File derived = new File(SLASH, file.getPath());
297 is = servletContext.getResourceAsStream(derived.getPath().replaceAll(REGEX_BACKSLASH, SLASH));
298 }
299 font = Font.createFont(Font.TRUETYPE_FONT, is);
300 if (log.isInfoEnabled()) log.info(SERVLET_LOAD + file.getPath().replaceAll(REGEX_BACKSLASH, SLASH));
301 } catch (Exception e) {
302 if (log.isEnabledFor(Priority.INFO))
303 log.info(SERVLET_LOADERROR + file.getPath().replaceAll(REGEX_BACKSLASH, SLASH));
304 }
305 }
306 return font;
307 }
308
309 protected InputStream loadFile(File file) throws IOException {
310 if (!file.isFile() && !file.exists()) {
311 throw new IOException(FILE_LOADERROR);
312 }
313 FileInputStream fis = new FileInputStream(file);
314 return fis;
315 }
316
317 protected InputStream loadUrl(URL url) throws IOException {
318 URLConnection connection = url.openConnection();
319 connection.connect();
320 DataInputStream remoteObj = new DataInputStream(connection.getInputStream());
321 return remoteObj;
322 }
323
324 public String toString() {
325 return "[" + this.getClass().getName() + "#" + this.hashCode() + "]";
326 }
327 }