KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > opensubsystems > core > util > FileUtils


1 /*
2  * Copyright (c) 2003 - 2007 OpenSubsystems s.r.o. Slovak Republic. All rights reserved.
3  *
4  * Project: OpenSubsystems
5  *
6  * $Id: FileUtils.java,v 1.12 2007/02/01 07:18:32 bastafidli Exp $
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; version 2 of the License.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */

21
22 package org.opensubsystems.core.util;
23
24 import java.io.BufferedInputStream JavaDoc;
25 import java.io.BufferedOutputStream JavaDoc;
26 import java.io.File JavaDoc;
27 import java.io.FileInputStream JavaDoc;
28 import java.io.FileOutputStream JavaDoc;
29 import java.io.IOException JavaDoc;
30 import java.io.InputStream JavaDoc;
31 import java.io.OutputStream JavaDoc;
32 import java.util.Arrays JavaDoc;
33 import java.util.Date JavaDoc;
34 import java.util.List JavaDoc;
35 import java.util.Properties JavaDoc;
36 import java.util.logging.Logger JavaDoc;
37
38 import org.opensubsystems.core.error.OSSException;
39 import org.opensubsystems.core.error.OSSMultiException;
40
41 /**
42  * Collection of methods to make work with files easier.
43  *
44  * @version $Id: FileUtils.java,v 1.12 2007/02/01 07:18:32 bastafidli Exp $
45  * @author Miro Halas
46  * @code.reviewer Miro Halas
47  * @code.reviewed 1.7 2006/05/21 03:45:37 bastafidli
48  */

49 public class FileUtils
50 {
51    // Configuration settings ///////////////////////////////////////////////////
52

53    /**
54     * Specifies what directory should be used to store generated and other
55     * temporary files and directories. This directory should be different from
56     * the regular operating system temporary directory since some of the subsystems
57     * may want to delete all content from this directory during restart.
58     */

59    public static final String JavaDoc TEMPORARY_DIRECTORY_PATH = "oss.file.path.temp";
60    
61    // Constants ////////////////////////////////////////////////////////////////
62

63    /**
64     * The default directory where temporary files should be created.
65     */

66    public static final String JavaDoc TEMPORARY_DIRECTORY_PATH_DEFAULT
67                                  = GlobalConstants.getTempDirectory() + "osstemp";
68    
69    /**
70     * Default 10 digit file storage distribution array. This means that if I
71     * want to name file as 10 digit number e.g. number 123 as 0000000123 or
72     * number 123456789 as 01234567890. Then the path constructed from number
73     * 1234567890 using distribution 2/2/2/4 would be 12/34/56/0123456789
74     */

75    public static final int[] DEFAULT_STRORAGE_TREE_DISTRIBUTION = {2, 2, 2, 4};
76    
77    /**
78     * How big buffer to use to process files.
79     */

80    public static final int BUFFER_SIZE = 65536;
81    
82    // Cached values ////////////////////////////////////////////////////////////
83

84    /**
85     * Logger for this class
86     */

87    private static Logger JavaDoc s_logger = Log.getInstance(FileUtils.class);
88    
89    /**
90     * Temporary directory to use. It is guarantee that it ends with \ (or /)
91     */

92    protected static String JavaDoc s_strTempDirectory;
93    
94    // Constructors /////////////////////////////////////////////////////////////
95

96    /**
97     * Static initializer
98     */

99    static
100    {
101       // Load the temporary path
102
Properties JavaDoc prpSettings;
103       
104       prpSettings = Config.getInstance().getPropertiesSafely();
105
106       s_strTempDirectory = Config.getStringProperty(
107                                      prpSettings,
108                                      TEMPORARY_DIRECTORY_PATH,
109                                      TEMPORARY_DIRECTORY_PATH_DEFAULT,
110                                      "Directory to store temporary files");
111       
112       if ((!s_strTempDirectory.endsWith(File.separator))
113          // On Windows it is allowed to end with / since java will shield it
114
&& (GlobalConstants.isWindows() && (!s_strTempDirectory.endsWith("/"))))
115       {
116          s_strTempDirectory += File.separator;
117       }
118       // Log this as finest since one config log was laready printed
119
s_logger.finest(TEMPORARY_DIRECTORY_PATH + " = " + s_strTempDirectory);
120    }
121    
122    // Public methods ///////////////////////////////////////////////////////////
123

124    /**
125     * Move file to a new location. If the destination is on different volume,
126     * this file will be copied and then original file will be deleted.
127     * If the destination already exists, this method renames it with different
128     * name and leaves it in that directory and moves the new file along side
129     * the renamed one.
130     *
131     * @param flCurrent - file to move
132     * @param strNewName - new location including file name
133     * @throws IOException - error message
134     * @throws OSSException - error message
135     */

136    public static void moveFile(
137       File JavaDoc flCurrent,
138       String JavaDoc strNewName
139    ) throws IOException JavaDoc,
140             OSSException
141    {
142       // Next check if the destination file exists
143
File JavaDoc flDestination;
144          
145       flDestination = new File JavaDoc(strNewName);
146       FileUtils.moveFile(flCurrent, flDestination);
147    }
148    
149    /**
150     * Move file to a new location. If the destination is on different volume,
151     * this file will be copied and then original file will be deleted.
152     * If the destination already exists, this method renames it with different
153     * name and leaves it in that directory and moves the new file along side
154     * the renamed one.
155     *
156     * @param flCurrent - file to move
157     * @param flDestination - destination file
158     * @throws IOException - error message
159     * @throws OSSException - error message
160     */

161    public static void moveFile(
162       File JavaDoc flCurrent,
163       File JavaDoc flDestination
164    ) throws IOException JavaDoc,
165             OSSException
166    {
167       // Make sure that the source exist, it might be already moved from
168
// a directory and we just don't know about it
169
if (flCurrent.exists())
170       {
171          // Next check if the destination file exists
172
if (flDestination.exists())
173          {
174             // If the destination exists, that means something went wrong
175
// Rename the destination file under temporaty name and try to
176
// move the new file instead of it
177
s_logger.warning("Destination file "
178                                       + flDestination.getAbsolutePath()
179                                       + " exists. Renaming as duplicate.");
180             renameToTemporaryName(flDestination, "old");
181          }
182       
183          // Make sure the directory exists and if not create it
184
File JavaDoc flFolder;
185          
186          flFolder = flDestination.getParentFile();
187          if ((flFolder != null) && (!flFolder.exists()))
188          {
189             if (!flFolder.mkdirs())
190             {
191                // Do not throw the exception if the directory already exists
192
// because it was created meanwhile for example by a different
193
// thread
194
if (!flFolder.exists())
195                {
196                   throw new IOException JavaDoc("Cannot create directory " + flFolder);
197                }
198             }
199          }
200          
201          // Now everything should exist so try to rename the file first
202
// After testing, this renames files even between volumes C to H
203
// so we don't have to do anything else on Windows but we still
204
// have to handle erro on Unix
205
if (!flCurrent.renameTo(flDestination))
206          {
207             // Try to copy and delete since the rename doesn't work on Solaris
208
// between file systems
209
copyFile(flCurrent, flDestination);
210             
211             // Now delete the file
212
if (!flCurrent.delete())
213             {
214                // Delete the destination file first since we haven't really moved
215
// the file
216
flDestination.delete();
217                throw new IOException JavaDoc("Cannot delete already copied file " + flCurrent);
218             }
219          }
220       }
221    }
222  
223    /**
224     * Copy the current file to the destination file.
225     *
226     * @param flCurrent - source file
227     * @param flDestination - destination file
228     * @throws IOException - error message
229     * @throws OSSException - error message
230     */

231    public static void copyFile(
232       File JavaDoc flCurrent,
233       File JavaDoc flDestination
234    ) throws IOException JavaDoc,
235             OSSException
236    {
237      // Make sure the directory exists and if not create it
238
File JavaDoc flFolder;
239      
240      flFolder = flDestination.getParentFile();
241      if ((flFolder != null) && (!flFolder.exists()))
242      {
243         if (!flFolder.mkdirs())
244         {
245            // Do not throw the exception if the directory already exists
246
// because it was created meanwhile for example by a different
247
// thread
248
if (!flFolder.exists())
249            {
250               throw new IOException JavaDoc("Cannot create directory " + flFolder);
251            }
252         }
253      }
254
255       // FileChannel srcChannel = null;
256
// FileChannel dstChannel = null;
257
FileInputStream JavaDoc finInput = null;
258       
259       //MHALAS: This code is not working reliably on Solaris 8 with 1.4.1_01
260
// Getting exceptions from native code
261
/*
262       // Create channel on the source
263       srcChannel = new FileInputStream(flCurrent).getChannel();
264       // Create channel on the destination
265       dstChannel = new FileOutputStream(flDestination).getChannel();
266  
267       // Copy file contents from source to destination
268       dstChannel.transferFrom(srcChannel, 0, srcChannel.size());
269          
270       Don't forget to close the channels if you enable this code again
271       */

272       try
273       {
274          finInput = new FileInputStream JavaDoc(flCurrent);
275       }
276       catch (IOException JavaDoc ioExec)
277       {
278          if (finInput != null)
279          {
280             try
281             {
282                finInput.close();
283             }
284             catch (Throwable JavaDoc thr)
285             {
286                throw new OSSMultiException(ioExec, thr);
287             }
288          }
289          throw ioExec;
290       }
291
292       FileUtils.copyStreamToFile(finInput, flDestination);
293    }
294    
295    /**
296     * Rename the file to temporaty name with given prefix
297     *
298     * @param flFileToRename - file to rename
299     * @param strPrefix - prefix to use
300     * @throws IOException - error message
301     */

302    public static void renameToTemporaryName(
303       File JavaDoc flFileToRename,
304       String JavaDoc strPrefix
305    ) throws IOException JavaDoc
306    {
307       assert strPrefix != null : "Prefix cannot be null.";
308       
309       String JavaDoc strParent;
310       StringBuffer JavaDoc sbBuffer = new StringBuffer JavaDoc();
311       File JavaDoc flTemp;
312       int iIndex = 0;
313       
314       strParent = flFileToRename.getParent();
315
316       // Generate new name for the file in a deterministic way
317
do
318       {
319          iIndex++;
320          sbBuffer.delete(0, sbBuffer.length());
321          if (strParent != null)
322          {
323             sbBuffer.append(strParent);
324             sbBuffer.append(File.separatorChar);
325          }
326          
327          sbBuffer.append(strPrefix);
328          sbBuffer.append("_");
329          sbBuffer.append(iIndex);
330          sbBuffer.append("_");
331          sbBuffer.append(flFileToRename.getName());
332                
333          flTemp = new File JavaDoc(sbBuffer.toString());
334       }
335       while (flTemp.exists());
336       
337       // Now we should have unique name
338
if (!flFileToRename.renameTo(flTemp))
339       {
340          throw new IOException JavaDoc("Cannot rename " + flFileToRename.getAbsolutePath()
341                                + " to " + flTemp.getAbsolutePath());
342       }
343    }
344
345    /**
346     * Delete all files and directories in directory but do not delete the
347     * directory itself.
348     *
349     * @param strDir - string that specifies directory to delete
350     * @return boolean - sucess flag
351     */

352    public static boolean deleteDirectoryContent(
353       String JavaDoc strDir
354    )
355    {
356       return ((strDir != null) && (strDir.length() > 0))
357               ? deleteDirectoryContent(new File JavaDoc(strDir)) : false;
358    }
359
360    /**
361     * Delete all files and directories in directory but do not delete the
362     * directory itself.
363     *
364     * @param fDir - directory to delete
365     * @return boolean - sucess flag
366     */

367    public static boolean deleteDirectoryContent(
368       File JavaDoc fDir
369    )
370    {
371       boolean bRetval = false;
372
373       if (fDir != null && fDir.isDirectory())
374       {
375          File JavaDoc[] files = fDir.listFiles();
376    
377          if (files != null)
378          {
379             bRetval = true;
380             boolean dirDeleted;
381             
382             for (int index = 0; index < files.length; index++)
383             {
384                if (files[index].isDirectory())
385                {
386                   // TODO: Performance: Implement this as a queue where you add to
387
// the end and take from the beginning, it will be more efficient
388
// than the recursion
389
dirDeleted = deleteDirectoryContent(files[index]);
390                   if (dirDeleted)
391                   {
392                      bRetval = bRetval && files[index].delete();
393                   }
394                   else
395                   {
396                      bRetval = false;
397                   }
398                }
399                else
400                {
401                   bRetval = bRetval && files[index].delete();
402                }
403             }
404          }
405       }
406
407       return bRetval;
408    }
409
410    /**
411     * Deletes all files and subdirectories under the specified directory including
412     * the specified directory
413     *
414     * @param strDir - string that specifies directory to be deleted
415     * @return boolean - true if directory was successfully deleted
416     */

417    public static boolean deleteDir(
418       String JavaDoc strDir
419    )
420    {
421       return ((strDir != null) && (strDir.length() > 0))
422                 ? deleteDir(new File JavaDoc(strDir)) : false;
423    }
424    
425    /**
426     * Deletes all files and subdirectories under the specified directory including
427     * the specified directory
428     *
429     * @param fDir - directory to be deleted
430     * @return boolean - true if directory was successfully deleted
431     */

432    public static boolean deleteDir(
433       File JavaDoc fDir
434    )
435    {
436       boolean bRetval = false;
437       if (fDir != null && fDir.exists())
438       {
439          bRetval = deleteDirectoryContent(fDir);
440          if (bRetval)
441          {
442             bRetval = bRetval && fDir.delete();
443          }
444       }
445       return bRetval;
446    }
447    
448    /**
449     * Compare binary files. Both files must be files (not directories) and exist.
450     *
451     * @param first - first file
452     * @param second - second file
453     * @return boolean - true if files are binery equal
454     * @throws IOException - error in function
455     */

456    public boolean isFileBinaryEqual(
457       File JavaDoc first,
458       File JavaDoc second
459    ) throws IOException JavaDoc
460    {
461       // TODO: Test: Missing test
462
boolean retval = false;
463       
464       if ((first.exists()) && (second.exists())
465          && (first.isFile()) && (second.isFile()))
466       {
467          if (first.getCanonicalPath().equals(second.getCanonicalPath()))
468          {
469             retval = true;
470          }
471          else
472          {
473             FileInputStream JavaDoc firstInput = null;
474             FileInputStream JavaDoc secondInput = null;
475             BufferedInputStream JavaDoc bufFirstInput = null;
476             BufferedInputStream JavaDoc bufSecondInput = null;
477
478             try
479             {
480                firstInput = new FileInputStream JavaDoc(first);
481                secondInput = new FileInputStream JavaDoc(second);
482                bufFirstInput = new BufferedInputStream JavaDoc(firstInput, BUFFER_SIZE);
483                bufSecondInput = new BufferedInputStream JavaDoc(secondInput, BUFFER_SIZE);
484    
485                int firstByte;
486                int secondByte;
487                
488                while (true)
489                {
490                   firstByte = bufFirstInput.read();
491                   secondByte = bufSecondInput.read();
492                   if (firstByte != secondByte)
493                   {
494                      break;
495                   }
496                   if ((firstByte < 0) && (secondByte < 0))
497                   {
498                      retval = true;
499                      break;
500                   }
501                }
502             }
503             finally
504             {
505                try
506                {
507                   if (bufFirstInput != null)
508                   {
509                      bufFirstInput.close();
510                   }
511                }
512                finally
513                {
514                   if (bufSecondInput != null)
515                   {
516                      bufSecondInput.close();
517                   }
518                }
519             }
520          }
521       }
522       
523       return retval;
524    }
525    
526    /**
527     * Create list of files in directory. Members if list are File structures.
528     *
529     * @param directory - File with directory
530     * @param maximum - maximum size of output list
531     * @param olderThan - file last modification time heve to by before this date
532     * @return List - list of File objects
533     */

534    public static List JavaDoc listFiles(
535       File JavaDoc directory,
536       int maximum,
537       Date JavaDoc olderThan
538    )
539    {
540       List JavaDoc lRetval = null;
541       if (directory != null && directory.isDirectory())
542       {
543          File JavaDoc[] files = null;
544          // TODO: Improve: I don't think this works, since the listFiles always
545
// returns all files. We can throw an exception and then catch it here
546
// and just let the filter remember the files which accepted to limit
547
// the amount of data searched
548
files = directory.listFiles(new MaximumFileFilter(maximum, olderThan));
549          
550          if (files != null)
551          {
552             lRetval = Arrays.asList(files);
553          }
554       }
555       return lRetval;
556    }
557    
558    /**
559     * Function converts parameters to full path and name in tree file storage
560     * using the default tree schema. For example id 123456.tif can be converted
561     * to 00\12\34\00123456.tif
562     *
563     * @param lID - id (decimal number) part of file name
564     * @param rootDirPath - root directory for file storage tree
565     * @param idExtension - extension after id part of name and before file extension
566     * can be empty or null
567     * @param fileExtension - file extension - with dot
568     * @return String - string with path and name for file
569     */

570    public static String JavaDoc getFileStoragePath(
571       long lID,
572       String JavaDoc rootDirPath,
573       String JavaDoc idExtension,
574       String JavaDoc fileExtension
575    )
576    {
577       return getFileStoragePath(lID, rootDirPath, idExtension, fileExtension,
578                                 DEFAULT_STRORAGE_TREE_DISTRIBUTION);
579    }
580    
581    /**
582     * Function converts parameters to full path and name in tree file storage.
583     * For example as id 123456.tif can be converted to 00\12\34\00123456.tif
584     *
585     * @param lID - id (decimal number) part of file name
586     * @param rootDirPath - root directory for file storage tree path. It have to end with
587     * separator char
588     * @param idExtension - extension after id part of name and before file extension
589     * can be empty or null
590     * @param fileExtension - file extension - with dot
591     * @param treeDistribution - tree distribution array. arrai of int > 0.
592     * @return String - string with path and name for file
593     */

594    public static String JavaDoc getFileStoragePath(
595       long lID,
596       String JavaDoc rootDirPath,
597       String JavaDoc idExtension,
598       String JavaDoc fileExtension,
599       int[] treeDistribution
600    )
601    {
602       int iDigit = 0;
603
604       StringBuffer JavaDoc idString = new StringBuffer JavaDoc(Long.toString(lID));
605       
606       StringBuffer JavaDoc retval = new StringBuffer JavaDoc(rootDirPath);
607       
608       for (int index = 0; index < treeDistribution.length; index++)
609       {
610          if (GlobalConstants.ERROR_CHECKING)
611          {
612             assert treeDistribution[index] > 0 : "value <= 0 in tree distribution array";
613          }
614          iDigit += treeDistribution[index];
615       }
616
617       if (GlobalConstants.ERROR_CHECKING)
618       {
619          assert idString.length() <= iDigit : "ID to big for three capacity";
620       }
621       
622       // append leading 0 characters
623
idString.insert(0, NumberUtils.ZEROCHARS, 0, iDigit - idString.length());
624       
625       // add subdirs to path
626
int currentCount = 0;
627       // Ignore the last element since thats just there to tell us what should
628
// be the total length of the desired file name
629
for (int index = 0; index < treeDistribution.length - 1; index++)
630       {
631          retval.append(idString.subSequence(
632                                    currentCount,
633                                    currentCount + treeDistribution[index]));
634          currentCount += treeDistribution[index];
635          retval.append(File.separator);
636       }
637       
638       // add file name part of path - complete id with leading 0 chars
639
retval.append(idString);
640       
641       // add id extension if any
642
if (idExtension != null && idExtension.length() > 0)
643       {
644          retval.append(idExtension);
645       }
646       // add file extension with leading dot
647
retval.append(fileExtension);
648       
649       return retval.toString();
650    }
651
652    /**
653     * Function will create TwoObjectStruct from full file path and name string
654     *
655     * @param filePath - file path and name
656     * @return TwoObjectStruct - file dir as first member and file name as
657     * second member
658     */

659    public static TwoObjectStruct getFilenameSplit(
660       String JavaDoc filePath
661    )
662    {
663       return new TwoObjectStruct(
664             filePath.substring(0, filePath.lastIndexOf(File.separator) + 1),
665             filePath.substring(filePath.lastIndexOf(File.separator) + 1));
666    }
667    
668    /**
669     * Get path which represents temporary directory. It is guarantee that it
670     * ends with \ (or /).
671     *
672     * @return String
673     */

674    public static String JavaDoc getTemporaryDirectory(
675    )
676    {
677       return s_strTempDirectory;
678    }
679    
680    /**
681     * Method constructs and returns repository path. If this constructed path
682     * does not exist, it will be automatically created.
683     *
684     * @param strPrefix - prefix to use to create directory name
685     * @param strTemporarySubDirID - string value used to create subdirectory
686     * of the parent directory
687     * @param bUseSession - if true then current session will be user as
688     * part of unique parh
689     * @return String - full path to the directory
690     * @throws IOException - error occured during creating of directory structure
691     */

692    public static String JavaDoc createTemporarySubdirectory(
693       String JavaDoc strPrefix,
694       String JavaDoc strTemporarySubDirID,
695       boolean bUseSession
696    ) throws IOException JavaDoc
697    {
698       StringBuffer JavaDoc sbRepositoryPath = new StringBuffer JavaDoc();
699       File JavaDoc fRepositoryPath;
700       
701       sbRepositoryPath.append(getTemporaryDirectory());
702       if (bUseSession)
703       {
704          sbRepositoryPath.append(CallContext.getInstance().getCurrentSession());
705          sbRepositoryPath.append(File.separator);
706       }
707       sbRepositoryPath.append(strPrefix);
708       sbRepositoryPath.append(strTemporarySubDirID);
709       sbRepositoryPath.append(File.separator);
710       
711       fRepositoryPath = new File JavaDoc(sbRepositoryPath.toString());
712
713       if (!fRepositoryPath.exists())
714       {
715          // all non-existent ancestor directories are automatically created
716
if (!fRepositoryPath.mkdirs())
717          {
718             // Do not throw the exception if the directory already exists
719
// because it was created meanwhile for example by a different
720
// thread
721
if (!fRepositoryPath.exists())
722             {
723                // Directory creation failed
724
throw new IOException JavaDoc(
725                   "Error occured during creating temporary directory.");
726             }
727          }
728       }
729       else if (bUseSession)
730       {
731          // Unique directory already exist but it hasn't
732
throw new IOException JavaDoc("Cannot create unique temporary directory because" +
733                                " it already exists.");
734       }
735
736       return sbRepositoryPath.toString();
737    }
738
739    /**
740     * Copy any input stream to output file. Once the data will be copied
741     * the stream will be closed.
742     *
743     * @param input - InputStream to copy from
744     * @param output - File to copy to
745     * @throws IOException - error in function
746     * @throws OSSMultiException - double error in function
747     */

748    public static void copyStreamToFile(
749       InputStream JavaDoc input,
750       File JavaDoc output
751    ) throws IOException JavaDoc,
752             OSSMultiException
753    {
754       FileOutputStream JavaDoc foutOutput = null;
755
756       // open input file as stream safe - it can throw some IOException
757
try
758       {
759          foutOutput = new FileOutputStream JavaDoc(output);
760       }
761       catch (IOException JavaDoc ioExec)
762       {
763          if (foutOutput != null)
764          {
765             try
766             {
767                foutOutput.close();
768             }
769             catch (IOException JavaDoc ioExec2)
770             {
771                throw new OSSMultiException(ioExec, ioExec2);
772             }
773          }
774          
775          throw ioExec;
776       }
777
778       // all streams including os are closed in copyStreamToStream function
779
// in any case
780
FileUtils.copyStreamToStream(input, foutOutput);
781    }
782
783    /**
784     * Copy any input stream to output stream. Once the data will be copied
785     * both streams will be closed.
786     *
787     * @param input - InputStream to copy from
788     * @param output - OutputStream to copy to
789     * @throws IOException - io error in function
790     * @throws OSSMultiException - double error in function
791     */

792    public static void copyStreamToStream(
793       InputStream JavaDoc input,
794       OutputStream JavaDoc output
795    ) throws IOException JavaDoc,
796             OSSMultiException
797    {
798       InputStream JavaDoc is = null;
799       OutputStream JavaDoc os = null;
800       int ch;
801
802       try
803       {
804          if (input instanceof BufferedInputStream JavaDoc)
805          {
806             is = input;
807          }
808          else
809          {
810             is = new BufferedInputStream JavaDoc(input);
811          }
812          if (output instanceof BufferedOutputStream JavaDoc)
813          {
814             os = output;
815          }
816          else
817          {
818             os = new BufferedOutputStream JavaDoc(output);
819          }
820    
821          while ((ch = is.read()) != -1)
822          {
823             os.write(ch);
824          }
825          os.flush();
826       }
827       finally
828       {
829          IOException JavaDoc exec1 = null;
830          IOException JavaDoc exec2 = null;
831          try
832          {
833             // because this close can throw exception we do next close in
834
// finally statement
835
if (os != null)
836             {
837                try
838                {
839                   os.close();
840                }
841                catch (IOException JavaDoc exec)
842                {
843                   exec1 = exec;
844                }
845             }
846          }
847          finally
848          {
849             if (is != null)
850             {
851                try
852                {
853                   is.close();
854                }
855                catch (IOException JavaDoc exec)
856                {
857                   exec2 = exec;
858                }
859             }
860          }
861          if ((exec1 != null) && (exec2 != null))
862          {
863             throw new OSSMultiException(exec1, exec2);
864          }
865          else if (exec1 != null)
866          {
867             throw exec1;
868          }
869          else if (exec2 != null)
870          {
871             throw exec2;
872          }
873       }
874    }
875 }
876
Popular Tags