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="https://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         }