001 package com.croftsoft.core.io;
002
003 import java.applet.*;
004 import java.io.*;
005 import java.util.zip.*;
006
007 import com.croftsoft.core.applet.AppletLib;
008 import com.croftsoft.core.jnlp.JnlpLib;
009 import com.croftsoft.core.lang.NullArgumentException;
010 import com.croftsoft.core.lang.Testable;
011
012 /*********************************************************************
013 * Saves and loads Serializable objects using GZIP compression.
014 *
015 * @version
016 * 2003-06-13
017 * @since
018 * 2001-04-25
019 * @author
020 * <a href="http://www.CroftSoft.com/">David Wallace Croft</a>
021 *********************************************************************/
022
023 public final class SerializableLib
024 //////////////////////////////////////////////////////////////////////
025 //////////////////////////////////////////////////////////////////////
026 {
027
028 private static final String PROPERTY_USER_HOME = "user.home";
029
030 //////////////////////////////////////////////////////////////////////
031 // test methods
032 //////////////////////////////////////////////////////////////////////
033
034 /*********************************************************************
035 * Displays the result of test().
036 *********************************************************************/
037 public static void main ( String [ ] args )
038 throws Exception
039 //////////////////////////////////////////////////////////////////////
040 {
041 System.out.println ( test ( args ) );
042 }
043
044 public static boolean test ( String [ ] args )
045 //////////////////////////////////////////////////////////////////////
046 {
047 try
048 {
049 final String TEST = "CroftSoft";
050
051 if ( !TEST.equals (
052 load ( new ByteArrayInputStream ( compress ( TEST ) ) ) ) )
053 {
054 return false;
055 }
056
057 String testCopy = ( String ) copy ( TEST );
058
059 if ( ( testCopy == TEST )
060 || !testCopy.equals ( TEST ) )
061 {
062 return false;
063 }
064 }
065 catch ( Exception ex )
066 {
067 ex.printStackTrace ( );
068
069 return false;
070 }
071
072 return true;
073 }
074
075 //////////////////////////////////////////////////////////////////////
076 //////////////////////////////////////////////////////////////////////
077
078 public static byte [ ] compress ( Serializable serializable )
079 throws IOException
080 //////////////////////////////////////////////////////////////////////
081 {
082 NullArgumentException.check ( serializable );
083
084 ByteArrayOutputStream byteArrayOutputStream
085 = new ByteArrayOutputStream ( );
086
087 save ( serializable, byteArrayOutputStream );
088
089 return byteArrayOutputStream.toByteArray ( );
090 }
091
092 public static Serializable copy ( Serializable serializable )
093 throws IOException
094 //////////////////////////////////////////////////////////////////////
095 {
096 ByteArrayOutputStream byteArrayOutputStream
097 = new ByteArrayOutputStream ( );
098
099 ObjectOutputStream objectOutputStream
100 = new ObjectOutputStream ( byteArrayOutputStream );
101
102 objectOutputStream.writeObject ( serializable );
103
104 byte [ ] bytes = byteArrayOutputStream.toByteArray ( );
105
106 ByteArrayInputStream byteArrayInputStream
107 = new ByteArrayInputStream ( bytes );
108
109 ObjectInputStream objectInputStream
110 = new ObjectInputStream ( byteArrayInputStream );
111
112 try
113 {
114 return ( Serializable ) objectInputStream.readObject ( );
115 }
116 catch ( ClassNotFoundException ex )
117 {
118 // This should never happen since the same classes are used.
119
120 throw new RuntimeException ( );
121 }
122 }
123
124 //////////////////////////////////////////////////////////////////////
125 // load methods
126 //////////////////////////////////////////////////////////////////////
127
128 public static Serializable load ( InputStream inputStream )
129 throws ClassNotFoundException, IOException
130 //////////////////////////////////////////////////////////////////////
131 {
132 NullArgumentException.check ( inputStream );
133
134 ObjectInputStream objectInputStream = null;
135
136 try
137 {
138 objectInputStream
139 = new ObjectInputStream (
140 new GZIPInputStream (
141 new BufferedInputStream ( inputStream ) ) );
142
143 return ( Serializable ) objectInputStream.readObject ( );
144 }
145 finally
146 {
147 if ( objectInputStream != null )
148 {
149 objectInputStream.close ( );
150 }
151 else
152 {
153 inputStream.close ( );
154 }
155 }
156 }
157
158 public static Serializable load ( String filename )
159 throws ClassNotFoundException, IOException
160 //////////////////////////////////////////////////////////////////////
161 {
162 NullArgumentException.check ( filename );
163
164 return load ( new FileInputStream ( filename ) );
165 }
166
167 public static Serializable load (
168 String primaryFilename,
169 String fallbackFilename )
170 throws ClassNotFoundException, IOException
171 //////////////////////////////////////////////////////////////////////
172 {
173 NullArgumentException.check ( primaryFilename );
174
175 if ( fallbackFilename == null )
176 {
177 return load ( primaryFilename );
178 }
179
180 try
181 {
182 return load ( primaryFilename );
183 }
184 catch ( FileNotFoundException ex )
185 {
186 }
187 catch ( Exception ex )
188 {
189 ex.printStackTrace ( );
190 }
191
192 return load ( fallbackFilename );
193 }
194
195 public static Serializable load (
196 ClassLoader classLoader,
197 String filename )
198 throws ClassNotFoundException, IOException
199 //////////////////////////////////////////////////////////////////////
200 {
201 NullArgumentException.check ( classLoader );
202
203 NullArgumentException.check ( filename );
204
205 InputStream inputStream
206 = classLoader.getResourceAsStream ( filename );
207
208 if ( inputStream == null )
209 {
210 return null;
211 }
212
213 return load ( inputStream );
214 }
215
216 public static Serializable load (
217 String primaryFilename,
218 String fallbackFilename,
219 String fileContentsSpec,
220 Applet applet,
221 String persistenceKey,
222 ClassLoader classLoader,
223 String resourcePathFilename )
224 throws ClassNotFoundException, IOException
225 //////////////////////////////////////////////////////////////////////
226 {
227 Serializable serializable = null;
228
229 if ( primaryFilename != null )
230 {
231 try
232 {
233 String userHomeDir = System.getProperty ( PROPERTY_USER_HOME );
234
235 String primaryPath
236 = userHomeDir + File.separator + primaryFilename;
237
238 if ( fallbackFilename != null )
239 {
240 String fallbackPath
241 = userHomeDir + File.separator + fallbackFilename;
242
243 serializable
244 = ( Serializable ) load ( primaryPath, fallbackPath );
245 }
246 else
247 {
248 serializable = ( Serializable ) load ( primaryPath );
249 }
250 }
251 catch ( FileNotFoundException ex )
252 {
253 }
254 catch ( SecurityException ex )
255 {
256 }
257 }
258
259 if ( ( serializable == null )
260 && ( fileContentsSpec != null ) )
261 {
262 try
263 {
264 serializable = ( Serializable )
265 JnlpLib.loadSerializableUsingPersistenceService (
266 fileContentsSpec );
267 }
268 catch ( UnsupportedOperationException ex )
269 {
270 }
271 }
272
273 if ( ( serializable == null )
274 && ( applet != null )
275 && ( persistenceKey != null ) )
276 {
277 try
278 {
279 serializable = ( Serializable )
280 AppletLib.loadSerializableUsingAppletPersistence (
281 applet, persistenceKey );
282 }
283 catch ( UnsupportedOperationException ex )
284 {
285 }
286 }
287
288 if ( ( serializable == null )
289 && ( classLoader != null )
290 && ( resourcePathFilename != null ) )
291 {
292 serializable
293 = ( Serializable ) load ( classLoader, resourcePathFilename );
294 }
295
296 return serializable;
297 }
298
299 //////////////////////////////////////////////////////////////////////
300 // save methods
301 //////////////////////////////////////////////////////////////////////
302
303 public static void save (
304 Serializable serializable,
305 OutputStream outputStream )
306 throws IOException
307 //////////////////////////////////////////////////////////////////////
308 {
309 NullArgumentException.check ( serializable );
310
311 NullArgumentException.check ( outputStream );
312
313 ObjectOutputStream objectOutputStream = null;
314
315 try
316 {
317 objectOutputStream = new ObjectOutputStream (
318 new GZIPOutputStream (
319 new BufferedOutputStream ( outputStream ) ) );
320
321 objectOutputStream.writeObject ( serializable );
322 }
323 finally
324 {
325 if ( objectOutputStream != null )
326 {
327 objectOutputStream.close ( );
328 }
329 else
330 {
331 outputStream.close ( );
332 }
333 }
334 }
335
336 public static void save (
337 Serializable serializable,
338 String filename,
339 boolean makeDirs )
340 throws IOException
341 //////////////////////////////////////////////////////////////////////
342 {
343 NullArgumentException.check ( serializable );
344
345 NullArgumentException.check ( filename );
346
347 if ( makeDirs )
348 {
349 FileLib.makeParents ( filename );
350 }
351
352 save ( serializable, new FileOutputStream ( filename ) );
353 }
354
355 public static void save (
356 Serializable serializable,
357 String filename )
358 throws IOException
359 //////////////////////////////////////////////////////////////////////
360 {
361 save ( serializable, filename, true );
362 }
363
364 public static void save (
365 Serializable serializable,
366 String latestFilename,
367 String backupFilename )
368 throws IOException
369 //////////////////////////////////////////////////////////////////////
370 {
371 NullArgumentException.check ( serializable );
372
373 NullArgumentException.check ( latestFilename );
374
375 NullArgumentException.check ( backupFilename );
376
377 File latestFile = new File ( latestFilename );
378
379 if ( latestFile.exists ( ) )
380 {
381 File backupFile = new File ( backupFilename );
382
383 if ( backupFile.exists ( ) )
384 {
385 backupFile.delete ( );
386 }
387 else
388 {
389 FileLib.makeParents ( backupFilename );
390 }
391
392 latestFile.renameTo ( backupFile );
393 }
394
395 save ( serializable, latestFilename );
396 }
397
398 public static boolean save (
399 Serializable serializable,
400 String latestFilename,
401 String backupFilename,
402 String fileContentsSpec,
403 Applet applet,
404 String persistenceKey )
405 throws IOException
406 //////////////////////////////////////////////////////////////////////
407 {
408 NullArgumentException.check ( serializable );
409
410 if ( latestFilename != null )
411 {
412 try
413 {
414 String userHomeDir = System.getProperty ( PROPERTY_USER_HOME );
415
416 String latestPath
417 = userHomeDir + File.separator + latestFilename;
418
419 if ( backupFilename != null )
420 {
421 String backupPath
422 = userHomeDir + File.separator + backupFilename;
423
424 save ( serializable, latestPath, backupPath );
425 }
426 else
427 {
428 save ( serializable, latestPath );
429 }
430
431 return true;
432 }
433 catch ( SecurityException ex )
434 {
435 }
436 }
437
438 if ( fileContentsSpec != null )
439 {
440 try
441 {
442 JnlpLib.saveSerializableUsingPersistenceService (
443 fileContentsSpec, serializable );
444
445 return true;
446 }
447 catch ( UnsupportedOperationException ex )
448 {
449 }
450 }
451
452 if ( ( applet != null )
453 && ( persistenceKey != null ) )
454 {
455 try
456 {
457 AppletLib.saveSerializableUsingAppletPersistence (
458 applet, persistenceKey, serializable );
459
460 return true;
461 }
462 catch ( UnsupportedOperationException ex )
463 {
464 }
465 }
466
467 return false;
468 }
469
470 //////////////////////////////////////////////////////////////////////
471 //////////////////////////////////////////////////////////////////////
472
473 private SerializableLib ( ) { }
474
475 //////////////////////////////////////////////////////////////////////
476 //////////////////////////////////////////////////////////////////////
477 }