1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.fjank.jcache.persistence;
20
21 import java.io.BufferedInputStream;
22 import java.io.ByteArrayInputStream;
23 import java.io.ByteArrayOutputStream;
24 import java.io.File;
25 import java.io.FileNotFoundException;
26 import java.io.IOException;
27 import java.io.NotSerializableException;
28 import java.io.ObjectInputStream;
29 import java.io.ObjectOutputStream;
30 import java.io.RandomAccessFile;
31 import java.io.Serializable;
32 import javax.util.jcache.DiskCacheException;
33 import org.fjank.jcache.CacheObject;
34 import org.fjank.jcache.DiskCacheObject;
35
36
37
38
39
40 public class CacheFileAdapter {
41
42 private final String filepath;
43
44
45 private RandomAccessFile raf;
46
47
48
49
50
51
52
53
54 public CacheFileAdapter(final File file) {
55 this.filepath = file.getAbsolutePath();
56 try {
57 raf = new RandomAccessFile(filepath, "rw");
58 } catch (FileNotFoundException e) {
59 throw new IllegalStateException(
60 "The disk cache could not be initialized.");
61 }
62 }
63
64
65
66
67
68
69 public String toString() {
70 return getClass().getName() + ", file:" + filepath;
71 }
72
73
74
75
76
77
78 public byte[] read(long pos) {
79 byte[] data = null;
80 boolean corrupted = false;
81 try {
82 synchronized (this) {
83 raf.seek(pos);
84 int datalen = raf.readInt();
85 if (datalen > raf.length()) {
86 corrupted = true;
87 } else {
88 raf.readFully(data = new byte[datalen]);
89 }
90 }
91 if (corrupted) {
92 throw new IllegalStateException("The Cache file is corrupted.");
93 }
94 return data;
95 } catch (IOException e) {
96 throw new IllegalStateException(e.getMessage());
97 }
98 }
99
100
101
102
103
104
105
106
107
108
109
110 public Serializable readObject(long pos) throws DiskCacheException {
111 byte[] data = read(pos);
112 return deSerialize(data);
113
114 }
115
116
117
118 public synchronized void append(byte[] data) throws DiskCacheException {
119 try {
120 write(data, raf.length());
121 } catch (IOException e) {
122 throw new DiskCacheException(e);
123 }
124 }
125
126 public synchronized void write(byte[] data, long pos) {
127 try {
128 raf.seek(pos);
129 raf.writeInt(data.length);
130 raf.write(data);
131 } catch (IOException e) {
132 throw new IllegalStateException(e.getMessage());
133 }
134 }
135
136
137
138
139
140
141
142
143
144 public void writeObject(final Serializable obj, final long pos) {
145 write(serialize(obj), pos);
146 }
147
148
149
150
151
152
153
154
155
156
157 public DiskElementDescriptor appendObject(CacheObject obj) {
158 long pos = -1;
159 DiskElementDescriptor ded = new DiskElementDescriptor();
160 byte[] data = serialize((Serializable) obj);
161 synchronized (this) {
162 pos = length();
163 ded.init(pos, data);
164 write(data, pos);
165 }
166 return ded;
167 }
168
169 public synchronized long length() {
170 try {
171 return raf.length();
172 } catch (IOException e) {
173 throw new IllegalStateException(e.getMessage());
174 }
175 }
176
177 public synchronized void close() {
178 try {
179 raf.close();
180 } catch (IOException e) {
181 throw new IllegalStateException(e.getMessage());
182 }
183 }
184
185 public synchronized void reset() {
186 close();
187 File f = new File(filepath);
188
189 int retries=10;
190
191 while (!f.delete()) {
192 retries--;
193 if(retries<=0) {
194 throw new IllegalStateException("Failed to delete " + f.getName());
195 }
196
197 try {
198 Thread.sleep(100);
199 } catch (InterruptedException e1) {
200
201 }
202 }
203 try {
204 raf = new RandomAccessFile(filepath, "rw");
205 } catch (FileNotFoundException e) {
206 throw new IllegalStateException(e.getMessage());
207 }
208 }
209
210 public static byte[] serialize(Serializable obj) {
211 ObjectOutputStream oos = null;
212 try {
213 ByteArrayOutputStream baos = new ByteArrayOutputStream();
214 oos = new ObjectOutputStream(baos);
215 oos.writeObject(obj);
216 return baos.toByteArray();
217 } catch (NotSerializableException e) {
218 throw new IllegalStateException(e.getMessage());
219 } catch (IOException e) {
220 throw new IllegalStateException(e.getMessage());
221 } finally {
222 if (oos != null) {
223 try {
224 oos.close();
225 } catch (IOException e) {
226 throw new IllegalStateException(
227 "Failed to close stream to DiskCache, "
228 + "cache may be corrupted. Reason: " + e.getMessage());
229 }
230 }
231 }
232 }
233 public static DiskCacheObject deSerialize(byte[] data) throws DiskCacheException {
234 ObjectInputStream ois = null;
235 try {
236 ByteArrayInputStream bais = new ByteArrayInputStream(data);
237 BufferedInputStream bis = new BufferedInputStream(bais);
238 ois=new ObjectInputStream(bis);
239 DiskCacheObject obj = (DiskCacheObject) ois.readObject();
240 obj.getCacheObject().resetRefCount();
241 return obj;
242 } catch (IOException e) {
243 throw new IllegalStateException("An exception occured when reading from the disk cache." +
244 " Reason: " + e.getMessage());
245 } catch (ClassNotFoundException e) {
246 throw new IllegalStateException("A class could not be found when deSerializing." +
247 " Reason: " + e.getMessage());
248 } finally {
249 if (ois != null) {
250 try {
251 ois.close();
252 } catch (IOException e) {
253 throw new IllegalStateException(
254 "Failed to close stream to DiskCache, "
255 + "cache may be corrupted. Reason: " + e.getMessage());
256 }
257 }
258 }
259 }
260 }