/Users/lyon/j4p/src/classUtils/pack/util/pool2/BasePooledObject.java
|
1 package classUtils.pack.util.pool2;
2
3 import java.io.BufferedInputStream;
4 import java.io.BufferedOutputStream;
5 import java.io.File;
6 import java.io.FileInputStream;
7 import java.io.FileNotFoundException;
8 import java.io.FileOutputStream;
9 import java.io.IOException;
10 import java.io.NotSerializableException;
11 import java.io.ObjectInputStream;
12 import java.io.ObjectOutputStream;
13 import java.io.Serializable;
14 import java.util.Random;
15
16
17
18 /**
19 * A base implementation of a pooled object employing file serialization
20 * for passivation purposes.
21 * <p>
22 * This class offer support for handling the passivability and passivation state,
23 * and for object passivation/activation.
24 *
25 * @version 1.0
26 * @author Cristiano Sadun
27 *
28 */
29 public abstract class BasePooledObject implements PooledObject {
30
31 private static Random random = new Random();
32 private Object original;
33 private boolean passivated;
34 private boolean originalAcquired;
35 private Object passivationLock = new Object();
36 private ObjectPool objectPool;
37
38 private File serializedFile;
39
40 protected BasePooledObject(ObjectPool objectPool, Object original) {
41 this.objectPool = objectPool;
42 this.original = original;
43 this.passivated = false;
44 this.originalAcquired = false;
45 }
46
47 /**
48 * @see classUtils.pack.util.pool2.PooledObject#_getOriginal()
49 */
50 public final Object _getOriginal() throws ActivationException {
51 synchronized (passivationLock) {
52 if (original == null)
53 _activate();
54 originalAcquired = true;
55 }
56 return original;
57
58 }
59
60 /**
61 * @see classUtils.pack.util.pool2.PooledObject#_releaseOriginal()
62 */
63 public final void _releaseOriginal() {
64 originalAcquired = false;
65 }
66
67 /**
68 * Activate the object. If the object has not been passivated,
69 * this method does nothing.
70 *
71 * @see classUtils.pack.util.pool2.PooledObject#_activate()
72 */
73 public final void _activate() throws ActivationException {
74 synchronized (passivationLock) {
75 if (!passivated)
76 return;
77
78 if (objectPool.getLogStream()!=null) {
79 objectPool.getLogStream().println("Activating passivated object from "+serializedFile);
80 }
81
82 ObjectInputStream ois = null;
83 try {
84 try {
85 ois =
86 new ObjectInputStream(
87 new BufferedInputStream(
88 new FileInputStream(serializedFile)));
89 } catch (IOException e) {
90 throw new ActivationException(
91 "Could not open passivated file " + serializedFile, e);
92 }
93 original = ois.readObject();
94 serializedFile = null;
95 passivated = false;
96
97 } catch (ClassNotFoundException e) {
98 throw new ActivationException(
99 "Could not find the class with which the pooled object has been serialized",
100 e);
101 } catch (IOException e) {
102 throw new ActivationException(
103 "Could not read the serialized object from file "
104 + serializedFile,
105 e);
106 } finally {
107 if (ois != null)
108 try {
109 ois.close();
110 } catch (IOException e) {
111 throw new ActivationException(
112 "Could not close the serialized object file "
113 + serializedFile,
114 e);
115 }
116 }
117
118 }
119 }
120
121 /**
122 * This method passivates objects via serialization.
123 * <p>
124 * The original object must be Serializable.
125 * <p>
126 * The object is assigned an unique file name in a directory
127 * whose name is the class name of the original object; it is
128 * then serialized using an <tt>ObjectOutputStream</tt>.
129 *
130 * @see classUtils.pack.util.pool2.PooledObject#_passivate()
131 */
132 public final void _passivate() throws PassivationException {
133 // Serialize the object to a file
134 synchronized (passivationLock) {
135
136 if (passivated) throw new PassivationException("Already passivated");
137
138 if (!objectPool.getPassivationManager().canPassivate(original.getClass()))
139 throw new PassivationException(
140 "Object " + original.toString() + " is intrinsecally not passivable");
141
142 if (originalAcquired) throw new PassivationException("Original object acquired");
143
144 File objDir =
145 new File(
146 objectPool.getConfiguration().getStorageDirectory(),
147 original.getClass().getName());
148 if (!objDir.exists())
149 if (!objDir.mkdirs())
150 throw new PassivationException(
151 "Cannot create passivation directory " + objDir);
152 serializedFile = new File(objDir, mkTmpFileName(original));
153
154 if (objectPool.getLogStream()!=null) {
155 objectPool.getLogStream().println("Passivating "+this+" to "+serializedFile);
156 }
157
158 ObjectOutputStream oos = null;
159 try {
160 try {
161 oos =
162 new ObjectOutputStream(
163 new BufferedOutputStream(
164 new FileOutputStream(serializedFile)));
165 } catch (IOException e) {
166 throw new PassivationException(
167 "Could not create file for passivated object",
168 e);
169 }
170
171 oos.writeObject(original);
172 original = null;
173 passivated = true;
174 } catch (NotSerializableException e) {
175 throw new PassivationException(
176 "The pooled object is not Serializable",
177 e);
178 } catch (IOException e) {
179 throw new PassivationException(
180 "Could not write passivated object to file",
181 e);
182 } finally {
183 if (oos != null)
184 try {
185 oos.close();
186 } catch (IOException e) {
187 throw new PassivationException(
188 "Could not close passivated object file",
189 e);
190 }
191 }
192 }
193
194 }
195
196 /**
197 * Method mkTmpFileName.
198 */
199 private String mkTmpFileName(Object obj) {
200 return System.currentTimeMillis()
201 + "_"
202 + obj.getClass().getName()
203 + random.nextInt(1000);
204 }
205
206 /**
207 * Return the current passivable.state.
208 * @return boolean
209 */
210 public boolean _isPassivableNow() {
211 return _isPassivable() && passivated==false && originalAcquired==false;
212 }
213
214 /**
215 * Return the invariant passivable.state, as determined by the passivation manager
216 * associated to this pooled object.
217 * <p>
218 * For example, a passivation manager may require that an object be serializable
219 * or implement a specific interface.
220 * @see BasePassivationManager#canPassivate(java.lang.Class)
221 * @return boolean
222 */
223 public boolean _isPassivable() {
224 //return Serializable.class.isAssignableFrom(objectPool.getObjectType());
225 return objectPool.getPassivationManager().canPassivate(objectPool.getObjectType());
226 }
227
228 /**
229 * Returns the passivated state.
230 * @return boolean
231 */
232 public boolean _isPassivated() {
233 return passivated;
234 }
235
236 /**
237 * Return the serialized File, or <b>null</b> if the object is not
238 * passivated.
239 * @return File
240 */
241 public File getSerializedFile() {
242 synchronized (passivationLock) {
243 return serializedFile;
244 }
245 }
246
247 public String toString() {
248 StringBuffer sb = new StringBuffer();
249 sb.append(
250 "Pooled ");
251 sb.append(objectPool.getObjectType().getName());
252 sb.append(" object");
253 if (passivated) {
254 sb.append("(passivated)");
255 } else {
256
257 if (original!=null) {
258 sb.append(" [");
259 sb.append(original.toString());
260 sb.append("] ");
261 }
262
263 if (_isPassivable())
264 sb.append("(active)");
265 else
266 sb.append("(not passivable)");
267 }
268 return sb.toString();
269 }
270 /**
271 * Returns the original.
272 * @return Object
273 */
274 protected Object getOriginal() {
275 return original;
276 }
277
278 /**
279 * Returns the objectPool.
280 * @return ExtendedObjectPool
281 */
282 public final ObjectPool getObjectPool() {
283 return objectPool;
284 }
285
286 final void setObjectPool(ObjectPool pool) {
287 if (objectPool!=null) throw new IllegalStateException("Object pool can be set only once");
288 this.objectPool=pool;
289 }
290 }
291