1
2
3
4 package org.rcfaces.core.internal.content;
5
6 import java.io.ByteArrayInputStream;
7 import java.io.File;
8 import java.io.FileInputStream;
9 import java.io.FileNotFoundException;
10 import java.io.IOException;
11 import java.io.InputStream;
12 import java.io.Serializable;
13 import java.net.FileNameMap;
14 import java.net.URLConnection;
15 import java.security.MessageDigest;
16 import java.util.HashMap;
17 import java.util.Map;
18
19 import org.apache.commons.logging.Log;
20 import org.apache.commons.logging.LogFactory;
21 import org.rcfaces.core.internal.Constants;
22 import org.rcfaces.core.internal.contentStorage.AbstractResolvedContent;
23 import org.rcfaces.core.internal.contentStorage.IResolvedContent;
24 import org.rcfaces.core.internal.lang.StringAppender;
25 import org.rcfaces.core.internal.util.Base64;
26 import org.rcfaces.core.internal.util.MessageDigestSelector;
27 import org.rcfaces.core.lang.IAdapterFactory;
28
29
30
31
32
33
34 public class ContentAdapterFactory implements IAdapterFactory {
35 private static final String REVISION = "$Revision: 1.3.4.1 $";
36
37 private static final Log LOG = LogFactory
38 .getLog(ContentAdapterFactory.class);
39
40 private static final String TEMP_PREFIX = "contentAdapter_";
41
42 protected static final Map suffixByMimeType = new HashMap(8);
43
44 protected static final FileNameMap fileNameMap = URLConnection
45 .getFileNameMap();
46
47 private static final long startTimeMillis = System.currentTimeMillis();
48
49 private final Object tempFileCounterLock = new Object();
50
51 private long tempFileCounter;
52
53 public Object getAdapter(Object adaptableObject, Class adapterType,
54 Object parameter) {
55
56 return null;
57 }
58
59 public static String getSuffixByMimeType(String contentType) {
60 return (String) suffixByMimeType.get(contentType.toLowerCase());
61 }
62
63 public Class[] getAdapterList() {
64 return new Class[] { IResolvedContent.class };
65 }
66
67 public File createTempFile(String contentType, String suffix)
68 throws IOException {
69 File file = null;
70
71 File tempFolder = getTempFolder();
72 if (tempFolder != null) {
73
74 for (;;) {
75 long id;
76 synchronized (tempFileCounterLock) {
77 id = tempFileCounter++;
78 }
79
80 file = new File(tempFolder, getTempPrefix() + startTimeMillis
81 + "_" + id + "." + suffix);
82
83 if (file.createNewFile()) {
84 break;
85 }
86 }
87 }
88
89 if (file == null) {
90 file = File.createTempFile(getTempPrefix(), "." + suffix);
91 }
92
93 file.deleteOnExit();
94
95 return file;
96 }
97
98 protected String getTempPrefix() {
99 return TEMP_PREFIX;
100 }
101
102 protected File getTempFolder() {
103 return null;
104 }
105
106
107
108
109
110
111 protected class FileResolvedContent extends AbstractResolvedContent
112 implements Serializable {
113 private static final String REVISION = "$Revision: 1.3.4.1 $";
114
115 private static final long serialVersionUID = 2045867975901327708L;
116
117 private final String contentType;
118
119 private final String suffix;
120
121 private final int length;
122
123 private final long lastModificationDate;
124
125 private final String specifiedResourceKey;
126
127 private String etag;
128
129 private String hashCode;
130
131 private byte fileSerialized[];
132
133 private transient File file;
134
135 public FileResolvedContent(String contentType, String suffix,
136 File file, String specifiedResourceKey, long lastModifiedDate) {
137 this.file = file;
138 this.contentType = contentType;
139 this.suffix = suffix;
140 this.specifiedResourceKey = specifiedResourceKey;
141
142 this.length = (int) file.length();
143 this.lastModificationDate = lastModifiedDate;
144
145 if (Constants.ETAG_SUPPORT || Constants.HASH_SUPPORT) {
146 computeHashCodes();
147 }
148 }
149
150 public String getContentType() {
151 return contentType;
152 }
153
154 public String getURLSuffix() {
155 return suffix;
156 }
157
158 public String getResourceKey() {
159 if (specifiedResourceKey == null) {
160 return specifiedResourceKey;
161 }
162
163 return super.getResourceKey();
164 }
165
166 public InputStream getInputStream() throws IOException {
167 if (fileSerialized != null) {
168 return new ByteArrayInputStream(fileSerialized);
169 }
170
171 return new FileInputStream(file);
172 }
173
174 public long getModificationDate() {
175 return lastModificationDate;
176 }
177
178 public int getLength() {
179 return length;
180 }
181
182 public String getETag() {
183 return etag;
184 }
185
186 public String getHash() {
187 return hashCode;
188 }
189
190 protected void finalize() throws Throwable {
191 if (file != null) {
192 try {
193 file.delete();
194 file = null;
195
196 } catch (Throwable ex) {
197 LOG.error("Can not delete file '" + file + "'.", ex);
198 }
199 }
200 super.finalize();
201 }
202
203 protected void computeHashCodes() {
204 MessageDigest etagMessageDigest = null;
205 MessageDigest hashMessageDigest = null;
206
207 if (Constants.ETAG_SUPPORT) {
208 etagMessageDigest = MessageDigestSelector
209 .getInstance(Constants.ETAG_DIGEST_ALGORITHMS);
210 }
211
212 if (Constants.HASH_SUPPORT) {
213 hashMessageDigest = MessageDigestSelector
214 .getInstance(Constants.HASH_DIGEST_ALGORITHMS);
215 }
216
217 if (hashMessageDigest == null && etagMessageDigest == null) {
218 return;
219 }
220
221 FileInputStream fileInputStream;
222 try {
223 fileInputStream = new FileInputStream(file);
224
225 } catch (FileNotFoundException e) {
226 LOG.error("Can not compute Etag and Hashcode for file '" + file
227 + "'." + e);
228 return;
229 }
230
231 try {
232 byte buffer[] = new byte[4096];
233
234 for (;;) {
235 int ret = fileInputStream.read(buffer);
236 if (ret < 1) {
237 break;
238 }
239
240 if (etagMessageDigest != null) {
241 etagMessageDigest.update(buffer, 0, ret);
242 }
243
244 if (hashMessageDigest != null) {
245 hashMessageDigest.update(buffer, 0, ret);
246 }
247 }
248
249 if (etagMessageDigest != null) {
250 byte etagDigest[] = etagMessageDigest.digest();
251
252 StringAppender sb = new StringAppender(
253 etagDigest.length * 2 + 16);
254 sb.append("\"rcfaces:");
255 for (int i = 0; i < etagDigest.length; i++) {
256 int v = etagDigest[i] & 0xff;
257 if (v < 16) {
258 sb.append('0');
259 }
260 sb.append(Integer.toHexString(v));
261 }
262
263 sb.append(':');
264 sb.append(Integer.toHexString(length));
265
266 sb.append('\"');
267 etag = sb.toString();
268
269 if (LOG.isDebugEnabled()) {
270 LOG.debug("Etag for file '" + file + "' = " + etag);
271 }
272 }
273
274 if (hashMessageDigest != null) {
275 byte hashDigest[] = hashMessageDigest.digest();
276
277 hashCode = Base64.encodeBytes(hashDigest,
278 Base64.DONT_BREAK_LINES);
279
280 if (LOG.isDebugEnabled()) {
281 LOG.debug("Hashcode for file '" + file + "' = "
282 + hashCode);
283 }
284 }
285
286 } catch (IOException e) {
287 LOG.error("Can not compute Etag and Hashcode for file '" + file
288 + "'.", e);
289
290 } finally {
291 try {
292 fileInputStream.close();
293
294 } catch (IOException e) {
295 LOG.error(e);
296 }
297 }
298 }
299
300 private void writeObject(java.io.ObjectOutputStream s)
301 throws java.io.IOException {
302
303 if (file != null) {
304 fileSerialized = new byte[length];
305
306 FileInputStream fin = new FileInputStream(file);
307 try {
308 fin.read(fileSerialized);
309
310 } catch (IOException ex) {
311 LOG.error(ex);
312
313 } finally {
314 try {
315 fin.close();
316
317 } catch (IOException ex) {
318 LOG.error(ex);
319 }
320 }
321
322 file = null;
323 }
324
325 s.defaultWriteObject();
326 }
327 }
328 }