1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 package com.sun.star.filter.config.tools.utils;
25 
26 // __________ Imports __________
27 
28 import java.io.*;
29 import java.lang.*;
30 import java.net.*;
31 import java.util.*;
32 
33 // __________ Implementation __________
34 
35 /**
36  * It collects some static helper functons to handle file system specific problems.
37  * Sometimes it's necessary to convert URL from/to system paths;
38  * or from string notation to structural versions (e.g. com.sun.star.util.URL).
39  * And sometimes java had another notation then the office it has.
40  * Further it provides functionality to work easiear with the java.io.File class of java.
41  *
42  *
43  */
44 public class FileHelper
45 {
46     // ____________________
47 
48     /**
49      * Because the office need URLs for loading/saving documents
50      * we must convert used system paths.
51      * And java use another notation for file URLs ... correct it.
52      *
53      * @param aSystemPath
54      *          represent the file in system notation
55      *
56      * @return [String]
57      *          a file url which represent the given system path
58      */
getFileURLFromSystemPath(java.io.File aSystemPath)59     public static java.lang.String getFileURLFromSystemPath(java.io.File aSystemPath)
60     {
61         System.out.println("TODO: must be adapted to java 1.3 :-(");
62         System.exit(-1);
63 /*TODO_JAVA
64         try
65         {
66             sFileURL = aSystemPath.toURI().toURL().toString();
67         }
68         catch( MalformedURLException exWrong )
69         {
70             sFileURL = null;
71         }
72 */
73         java.lang.String sFileURL = null;
74 
75         // problem of java: file URL's are coded with 1 slash instead of 2 or 3 ones!
76         // => correct this problem first, otherwise office can't use these URL's
77         if(
78             (sFileURL                       != null ) &&
79             (sFileURL.startsWith("file:/")  == true ) &&
80             (sFileURL.startsWith("file://") == false)
81           )
82         {
83             java.lang.StringBuffer sWorkBuffer = new java.lang.StringBuffer(sFileURL);
84             sWorkBuffer.insert(6,"//");
85             sFileURL = sWorkBuffer.toString();
86         }
87 
88         return sFileURL;
89     }
90 
91     // ____________________
92 
93     /**
94      * The same as getFileURLFromSystemPath() before but uses string parameter instead
95      * of a java.io.File type. It exist to suppress converting of necessary parameters in the
96      * outside code. But of course getFileURLFromSystemPath(File) will be a little bit faster
97      * then this method ...
98      *
99      * @param sSystemPath
100      *          represent the file in system notation
101      *
102      * @return [String]
103      *          a file url which represent the given system path
104      */
getFileURLFromSystemPath(java.lang.String sSystemPath)105     public static java.lang.String getFileURLFromSystemPath(java.lang.String sSystemPath)
106     {
107         return getFileURLFromSystemPath(new java.io.File(sSystemPath));
108     }
109 
110     // ____________________
111 
112     /**
113      * Does the same as getFileURLFromSystemPath() before ... but uses
114      * the given protocol string (e.g."http://") instead of "file:///".
115      *
116      * @param aSystemPath
117      *          represent the file in system notation
118      *
119      * @param aBasePath
120      *          define the base path of the aSystemPath value,
121      *          which must be replaced with the value of "sServerPath".
122      *
123      * @param sServerURL
124      *          Will be used to replace sBasePath.
125      *
126      * @example
127      *          System Path = "d:\test\file.txt"
128      *          Base Path   = "d:\test"
129      *          Server Path = "http://alaska:8000"
130      *          => "http://alaska:8000/file.txt"
131      *
132      * @return [String]
133      *          an url which represent the given system path
134      *          and uses the given protocol
135      */
getURLWithProtocolFromSystemPath(java.io.File aSystemPath, java.io.File aBasePath , java.lang.String sServerURL )136     public static java.lang.String getURLWithProtocolFromSystemPath(java.io.File     aSystemPath,
137                                                                     java.io.File     aBasePath  ,
138                                                                     java.lang.String sServerURL )
139     {
140         System.out.println("TODO: must be adapted to java 1.3 :-(");
141         System.exit(-1);
142 
143         java.lang.String sFileURL = FileHelper.getFileURLFromSystemPath(aSystemPath);
144         java.lang.String sBaseURL = FileHelper.getFileURLFromSystemPath(aBasePath  );
145 
146         // cut last '/'!
147         if (sBaseURL.lastIndexOf('/')==(sBaseURL.length()-1))
148             sBaseURL = sBaseURL.substring(0,sBaseURL.length()-1);
149 
150         // cut last '/'!
151         if (sServerURL.lastIndexOf('/')==(sServerURL.length()-1))
152             sServerURL = sServerURL.substring(0,sServerURL.length()-1);
153 
154 //TODO_JAVA        java.lang.String sURL = sFileURL.replaceFirst(sBaseURL,sServerURL);
155         java.lang.String sURL = null;
156         return sURL;
157     }
158 
159     // ____________________
160 
161     /**
162      * The same as getURLWithProtocolFromSystemPath() before but uses string parameter instead
163      * of a java.io.File types. It exist to suppress converting of necessary parameters in the
164      * outside code. But of course getURLWithProtocolFromSystemPath(File,File,String) will be
165      * a little bit faster then this method ...
166      *
167      * @param sSystemPath
168      *          represent the file in system notation
169      *
170      * @param sBasePath
171      *          define the base path of the aSystemPath value,
172      *          which must be replaced with the value of "sServerPath".
173      *
174      * @param sServerPath
175      *          Will be used to replace sBasePath.
176      *
177      * @example
178      *          System Path = "d:\test\file.txt"
179      *          Base Path   = "d:\test"
180      *          Server Path = "http://alaska:8000"
181      *          => "http://alaska:8000/file.txt"
182      *
183      * @return [String]
184      *          an url which represent the given system path
185      *          and uses the given protocol
186      */
getURLWithProtocolFromSystemPath(java.lang.String sSystemPath, java.lang.String sBasePath , java.lang.String sServerPath)187     public static java.lang.String getURLWithProtocolFromSystemPath(java.lang.String sSystemPath,
188                                                                     java.lang.String sBasePath  ,
189                                                                     java.lang.String sServerPath)
190     {
191         return getURLWithProtocolFromSystemPath(new java.io.File(sSystemPath), new java.io.File(sBasePath), sServerPath);
192     }
193 
194     //_________________________________
195 
196     /**
197      * Return a list of all available files of a directory.
198      * We filter sub directories. All other files
199      * are returned. So they can be used for further purposes.
200      * One parameter define the start directory,
201      * another one enable/disable recursive search into sub directories.
202      *
203      * @param   aRoot
204      *          the start directory, which should be analyzed.
205      *
206      * @param   bRecursive
207      *          enable/disable search in sub directories.
208      *
209      * @return  [Vector]
210      *          a filtered list of java java.io.File objects of all available files
211      *          of the start dir (and may of its sub directories).
212      */
getSystemFilesFromDir(java.io.File aRoot , boolean bRecursive)213     public static java.util.Vector getSystemFilesFromDir(java.io.File aRoot     ,
214                                                          boolean      bRecursive)
215     {
216         java.io.File[] lAllFiles = aRoot.listFiles();
217         if (lAllFiles == null)
218             return null;
219 
220         int              c              = lAllFiles.length;
221         java.util.Vector lFilteredFiles = new java.util.Vector(c);
222         for (int i=0; i<c; ++i)
223         {
224             // simple files!
225             if (lAllFiles[i].isFile())
226                 lFilteredFiles.add(lAllFiles[i]);
227             else
228             // recursion?
229             if (bRecursive && lAllFiles[i].isDirectory())
230             {
231                 java.util.Vector lSubFiles = FileHelper.getSystemFilesFromDir(lAllFiles[i],bRecursive);
232                 if (lSubFiles != null)
233                 {
234                     java.util.Enumeration aSnapshot = lSubFiles.elements();
235                     while (aSnapshot.hasMoreElements())
236                         lFilteredFiles.add(aSnapshot.nextElement());
237                 }
238             }
239         }
240 
241         return lFilteredFiles;
242     }
243 
244     //_________________________________
245     /** it converts the given name (e.g. an internal type name) to
246      *  an usable system file name.
247      *
248      *  Do so some special characters (e.g. "/") must be replaced with other ones.
249      *
250      *  @param  sName
251      *              the name, which should be analyzed and converted.
252      *
253      *  @return A valid system file name, which should be similar to the
254      *          given name, but does not contain special characters any longer.
255      */
convertName2FileName(String sName)256     public static java.lang.String convertName2FileName(String sName)
257     {
258         int    i       = 0;
259         int    nLength = sName.length();
260         char[] lBuffer = sName.toCharArray();
261 
262         java.lang.StringBuffer sNewName = new java.lang.StringBuffer(nLength);
263         for (i=0; i<nLength; ++i)
264         {
265             char c = lBuffer[i];
266             if (
267                 c>=48 && c<=57      // 0-9
268                 &&
269                 c>=97 && c<=122     // a-z
270                 &&
271                 c>=65 && c<=90      // A-Z
272                )
273             {
274                 sNewName.append(c);
275             }
276             else
277             {
278                 sNewName.append("_");
279             }
280         }
281 
282         return sNewName.toString();
283     }
284 
285     //___________________________________________
286 
287     /** it removes all child nodes of a file system directory.
288      *
289      *  @param  aDirectory
290      *          points to the directory, which should be made empty.
291      *
292      *  @param  bFilesOnly
293      *          force deletion of files only. If its set to TRUE,
294      *          no subdirectory will be removed.
295      *
296      *  @throw  [java.io.IOException]
297      *          if some of the child nodes couldn't be removed.
298      */
makeDirectoryEmpty(java.io.File aDirectory, boolean bFilesOnly)299     public static void makeDirectoryEmpty(java.io.File aDirectory,
300                                           boolean      bFilesOnly)
301         throws java.io.IOException
302     {
303         if (!aDirectory.isDirectory())
304             throw new java.io.FileNotFoundException("\""+aDirectory.toString()+"\" is not a directory.");
305 
306         java.io.File[] lChilds = aDirectory.listFiles();
307         for (int f=0; f<lChilds.length; ++f)
308         {
309             if (lChilds[f].isDirectory())
310             {
311                 FileHelper.makeDirectoryEmpty(lChilds[f], bFilesOnly);
312                 if (!bFilesOnly)
313                 {
314                     if (!lChilds[f].delete())
315                         throw new java.io.IOException("\""+lChilds[f].toString()+"\" could not be deleted.");
316                 }
317             }
318             else
319             {
320                 if (!lChilds[f].delete())
321                     throw new java.io.IOException("\""+lChilds[f].toString()+"\" could not be deleted.");
322             }
323         }
324     }
325 
326     //___________________________________________
327 
328     /** it try to generate a new file with a unique ID
329      *  inside given directory.
330      *
331      *  Call this method with a directory and a base name for
332      *  a file. It will be used to generate a new files inside
333      *  the directory. Existing files will be checked and new file
334      *  name will be tested till a non existing file name would be found.
335      *
336      *  @param  aBaseDir
337      *          must be a system path
338      *          e.g.: "c:\temp"
339      *
340      *  @param  sBaseName
341      *          must be a system file name without extensions.
342      *          e.g.: "myfile_"
343      *
344      *  @param  sExtension
345      *          the whished extension.
346      *          e.g.: "dat"
347      *
348      *  @return A valid file object, if an unique file could be created -
349      *          Null otherwise.
350      *          e.g.: "c:\temp\myfile_1.dat"
351      */
createUniqueFile(java.io.File aBaseDir , java.lang.String sBaseName , java.lang.String sExtension)352     public static java.io.File createUniqueFile(java.io.File     aBaseDir  ,
353                                                 java.lang.String sBaseName ,
354                                                 java.lang.String sExtension)
355     {
356         java.io.File aBaseFile = new java.io.File(aBaseDir, sBaseName);
357         java.io.File aFile     = null;
358         long         nr        = 0;
359         while (aFile == null && nr < java.lang.Long.MAX_VALUE)
360         {
361             java.lang.String sFileName = aBaseFile.getPath() + java.lang.String.valueOf(nr) + "." + sExtension;
362             aFile = new java.io.File(sFileName);
363             if (aFile.exists())
364                 aFile=null;
365             ++nr;
366         }
367         return aFile;
368     }
369 
370     //___________________________________________
371 
372     /** reads the complete file, using the right encoding,
373      *  into the given string buffer.
374      *
375      *  @param  aFile
376      *          must point to a system file, which must exist.
377      *          e.g.: "c:\temp\test.txt"
378      *                "/tmp/test.txt"
379      *
380      *  @param  sEncoding
381      *          will be used to encode the string content
382      *          inside the file.
383      *          e.g.: "UTF8"
384      *
385      *  @param  sBuffer
386      *          used to return the file content.
387      *
388      *  @throw  [IOException]
389      *          - if the file couldn't be opened
390      *          - if the file does not use the right encoding
391      */
readEncodedBufferFromFile(java.io.File aFile , java.lang.String sEncoding, java.lang.StringBuffer sBuffer )392     public static void readEncodedBufferFromFile(java.io.File           aFile    ,
393                                                  java.lang.String       sEncoding,
394                                                  java.lang.StringBuffer sBuffer  )
395         throws java.io.IOException
396     {
397         if (sEncoding.equals("UTF-8Special"))
398         {
399             FileHelper.readAndCheckUTF8File(aFile,sBuffer);
400             return;
401         }
402 
403         java.io.FileInputStream   aByteStream    = new java.io.FileInputStream(aFile.getAbsolutePath());
404         java.io.InputStreamReader aEncodedReader = new java.io.InputStreamReader(aByteStream, sEncoding);
405         char[]                    aEncodedBuffer = new char[4096];
406         int                       nReadCount     = 0;
407 
408         while((nReadCount=aEncodedReader.read(aEncodedBuffer))>0)
409             sBuffer.append(aEncodedBuffer, 0, nReadCount);
410 
411         aEncodedReader.close();
412     }
413 
414     //___________________________________________
logEncodingData(java.lang.StringBuffer sLog , int nUTF8 , int nByteOrg1 , int nByteOrg2 , int nByteOrg3 , int nByteOrg4 , int nByte1 , int nByte2 , int nByte3 , int nByte4 , int nEncodingType)415     private static void logEncodingData(java.lang.StringBuffer sLog         ,
416                                         int                    nUTF8        ,
417                                         int                    nByteOrg1    ,
418                                         int                    nByteOrg2    ,
419                                         int                    nByteOrg3    ,
420                                         int                    nByteOrg4    ,
421                                         int                    nByte1       ,
422                                         int                    nByte2       ,
423                                         int                    nByte3       ,
424                                         int                    nByte4       ,
425                                         int                    nEncodingType)
426     {
427         sLog.append("["+nEncodingType+"]\t");
428         sLog.append((int)nUTF8+"\t=");
429         sLog.append("\t"+nByteOrg1+"/"+nByte1);
430         sLog.append("\t"+nByteOrg2+"/"+nByte2);
431         sLog.append("\t"+nByteOrg3+"/"+nByte3);
432         sLog.append("\t"+nByteOrg4+"/"+nByte4);
433         sLog.append("\n");
434     }
435 
436     //___________________________________________
impl_convertBytesToChar(int nByte1, int nByte2, int nByte3, int nByte4)437     private static char impl_convertBytesToChar(int nByte1, int nByte2, int nByte3, int nByte4)
438     {
439         return (char)((nByte1*0x40000)+(nByte2*0x1000)+(nByte3*0x40)+nByte4);
440     }
441 
442     //___________________________________________
impl_readAndCheckNextByte(byte[] aBuffer , int nBufPos , int nBufLength , int nMinRange , int nMaxRange )443     private static int impl_readAndCheckNextByte(byte[] aBuffer    ,
444                                                  int    nBufPos    ,
445                                                  int    nBufLength ,
446                                                  int    nMinRange  ,
447                                                  int    nMaxRange  )
448         throws java.lang.Exception
449     {
450         if (nBufPos>=nBufLength)
451             throw new java.lang.Exception("impl_readAndCheckNextByte()\nEnd of buffer reached.");
452 
453         int nByte = aBuffer[nBufPos] & 0xFF;
454         if (
455             (nByte < nMinRange) ||
456             (nByte > nMaxRange)
457            )
458         {
459             throw new java.lang.Exception("impl_readAndCheckNextByte()\nByte does not fit the specified range.");
460         }
461 
462         return nByte;
463     }
464 
465     //___________________________________________
readAndCheckUTF8File(java.io.File aFile , java.lang.StringBuffer sBuffer)466     public static void readAndCheckUTF8File(java.io.File           aFile  ,
467                                             java.lang.StringBuffer sBuffer)
468         throws java.io.IOException
469     {
470         java.io.FileInputStream aByteStream     = new java.io.FileInputStream(aFile.getAbsolutePath());
471         byte[]                  aBuffer         = new byte[4096];
472         int                     nReadCount      = 0;
473         int                     nByteOrg_1      = 0;
474         int                     nByteOrg_2      = 0;
475         int                     nByteOrg_3      = 0;
476         int                     nByteOrg_4      = 0;
477         int                     nByte_1         = 0;
478         int                     nByte_2         = 0;
479         int                     nByte_3         = 0;
480         int                     nByte_4         = 0;
481         char                    nUTF8           = 0;
482         int                     i               = 0;
483         int                     nEncodingType   = 0;
484         java.lang.StringBuffer  sLog            = new java.lang.StringBuffer();
485 
486         try
487         {
488 
489         while((nReadCount=aByteStream.read(aBuffer))>0)
490         {
491             i=0;
492             while (i<nReadCount)
493             {
494                 nByteOrg_1    = 0;
495                 nByteOrg_2    = 0;
496                 nByteOrg_3    = 0;
497                 nByteOrg_4    = 0;
498                 nByte_1       = 0;
499                 nByte_2       = 0;
500                 nByte_3       = 0;
501                 nByte_4       = 0;
502                 nUTF8         = 0;
503                 nEncodingType = 0;
504 
505                 nByteOrg_1 = aBuffer[i++] & 0xFF;
506                 nByte_1    = nByteOrg_1;
507                 /*
508                     Table 3-6. Well-Formed UTF-8 Byte Sequences
509 
510                     ============================================================================
511                     Nr.     Code Points             1st Byte    2nd Byte    3rd Byte    4th Byte
512                     ============================================================================
513                     01      U+     0..U+    7F      00..7F
514                     02      U+    80..U+   7FF      C2..DF      80..BF
515                     03      U+   800..U+   FFF      E0          A0..BF      80..BF
516                     04      U+  1000..U+  CFFF      E1..EC      80..BF      80..BF
517                     05      U+  D000..U+  D7FF      ED          80..9F      80..BF
518                     06      U+  E000..U+  FFFF      EE..EF      80..BF      80..BF
519                     07      U+ 10000..U+ 3FFFF      F0          90..BF      80..BF      80..BF
520                     08      U+ 40000..U+ FFFFF      F1..F3      80..BF      80..BF      80..BF
521                     09      U+100000..U+10FFFF      F4          80..8F      80..BF      80..BF
522                 */
523                 // ------------------------------------------------------------
524                 // 01
525                 // 1 byte: 0xxxxxxx
526                 // ------------------------------------------------------------
527                 if (
528                     (nByteOrg_1 >= 0x00) &&
529                     (nByteOrg_1 <= 0x7F)
530                    )
531                 {
532                     nEncodingType = 1;
533                     nUTF8         = (char)nByte_1;
534                 }
535                 // ------------------------------------------------------------
536                 // 02
537                 // 1 byte: 110xxxxx
538                 // 2 byte: 101xxxxx
539                 // ------------------------------------------------------------
540                 else
541                 if (
542                     (nByteOrg_1 >= 0xC2) &&
543                     (nByteOrg_1 <= 0xDF)
544                    )
545                 {
546                     nEncodingType = 2;
547                     nByteOrg_2    = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0x80, 0xBF);
548                     nByte_1       = nByteOrg_1-0xC2;
549                     nByte_2       = nByteOrg_2-0x80;
550                     nUTF8         = FileHelper.impl_convertBytesToChar(0,0,nByte_1, nByte_2);
551                 }
552                 // ------------------------------------------------------------
553                 // 03
554                 // 1 byte: 11100000
555                 // 2 byte: 101xxxxx
556                 // 3 byte: 10xxxxxx
557                 // ------------------------------------------------------------
558                 else
559                 if (nByteOrg_1 == 0xE0)
560                 {
561                     nEncodingType = 3;
562                     nByteOrg_2    = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0xA0, 0xBF);
563                     nByteOrg_3    = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0x80, 0xBF);
564                     nByte_2       = nByteOrg_2-0xA0;
565                     nByte_3       = nByteOrg_3-0x80;
566                     nUTF8         = FileHelper.impl_convertBytesToChar(0,0,nByte_2, nByte_3);
567                 }
568                 // ------------------------------------------------------------
569                 // 04
570                 // 1 byte: 111xxxxx
571                 // 2 byte: 10xxxxxx
572                 // 3 byte: 10xxxxxx
573                 // ------------------------------------------------------------
574                 else
575                 if (
576                     (nByteOrg_1 >= 0xE1) &&
577                     (nByteOrg_1 <= 0xEC)
578                    )
579                 {
580                     nEncodingType = 4;
581                     nByteOrg_2    = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0x80, 0xBF);
582                     nByteOrg_3    = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0x80, 0xBF);
583                     nByte_1       = nByteOrg_1-0xE1;
584                     nByte_2       = nByteOrg_2-0x80;
585                     nByte_3       = nByteOrg_3-0x80;
586                     nUTF8         = FileHelper.impl_convertBytesToChar(0,nByte_1, nByte_2, nByte_3);
587                 }
588                 // ------------------------------------------------------------
589                 // 05
590                 // 1 byte: 11101101
591                 // 2 byte: 10xxxxxx
592                 // 3 byte: 10xxxxxx
593                 // ------------------------------------------------------------
594                 else
595                 if (nByteOrg_1 == 0xED)
596                 {
597                     nEncodingType = 5;
598                     nByteOrg_2    = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0x80, 0x9F);
599                     nByteOrg_3    = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0x80, 0xBF);
600                     nByte_2       = nByteOrg_2-0x80;
601                     nByte_3       = nByteOrg_3-0x80;
602                     nUTF8         = FileHelper.impl_convertBytesToChar(0,0, nByte_2, nByte_3);
603                 }
604                 // ------------------------------------------------------------
605                 // 06
606                 // 1 byte: 1110111x
607                 // 2 byte: 10xxxxxx
608                 // 3 byte: 10xxxxxx
609                 // ------------------------------------------------------------
610                 else
611                 if (
612                     (nByteOrg_1 >= 0xEE) &&
613                     (nByteOrg_1 <= 0xEF)
614                    )
615                 {
616                     nEncodingType = 6;
617                     nByteOrg_2    = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0x80, 0xBF);
618                     nByteOrg_3    = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0x80, 0xBF);
619                     nByte_1       = nByteOrg_1-0xEE;
620                     nByte_2       = nByteOrg_2-0x80;
621                     nByte_3       = nByteOrg_3-0x80;
622                     nUTF8         = FileHelper.impl_convertBytesToChar(0,nByte_1, nByte_2, nByte_3);
623                 }
624                 // ------------------------------------------------------------
625                 // 07
626                 // 1 byte: 11110000
627                 // 2 byte: 1001xxxx
628                 // 3 byte: 10xxxxxx
629                 // 4 byte: 10xxxxxx
630                 // ------------------------------------------------------------
631                 else
632                 if (nByteOrg_1 == 0xF0)
633                 {
634                     nEncodingType = 7;
635                     nByteOrg_2    = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0x90, 0xBF);
636                     nByteOrg_3    = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0x80, 0xBF);
637                     nByteOrg_4    = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0x80, 0xBF);
638                     nByte_2       = nByteOrg_2-0x90;
639                     nByte_3       = nByteOrg_3-0x80;
640                     nByte_4       = nByteOrg_4-0x80;
641                     nUTF8         = FileHelper.impl_convertBytesToChar(0, nByte_2, nByte_3, nByte_4);
642                 }
643                 // ------------------------------------------------------------
644                 // 08
645                 // 1 byte: 111100xx
646                 // 2 byte: 10xxxxxx
647                 // 3 byte: 10xxxxxx
648                 // 3 byte: 10xxxxxx
649                 // ------------------------------------------------------------
650                 else
651                 if (
652                     (nByteOrg_1 >= 0xF1) &&
653                     (nByteOrg_1 <= 0xF3)
654                    )
655                 {
656                     nEncodingType = 8;
657                     nByteOrg_2    = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0x80, 0xBF);
658                     nByteOrg_3    = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0x80, 0xBF);
659                     nByteOrg_4    = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0x80, 0xBF);
660                     nByte_1       = nByteOrg_1-0xF1;
661                     nByte_2       = nByteOrg_2-0x80;
662                     nByte_3       = nByteOrg_3-0x80;
663                     nByte_4       = nByteOrg_4-0x80;
664                     nUTF8         = FileHelper.impl_convertBytesToChar(nByte_1, nByte_2, nByte_3, nByte_4);
665                 }
666                 // ------------------------------------------------------------
667                 // 09
668                 // 1 byte: 11110100
669                 // 2 byte: 10xxxxxx
670                 // 3 byte: 10xxxxxx
671                 // 4 byte: 10xxxxxx
672                 // ------------------------------------------------------------
673                 else
674                 if (nByteOrg_1 == 0xF0)
675                 {
676                     nEncodingType = 9;
677                     nByteOrg_2    = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0x80, 0xBF);
678                     nByteOrg_3    = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0x80, 0xBF);
679                     nByteOrg_4    = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0x80, 0xBF);
680                     nByte_2       = nByteOrg_2-0x80;
681                     nByte_3       = nByteOrg_3-0x80;
682                     nByte_4       = nByteOrg_4-0x80;
683                     nUTF8         = FileHelper.impl_convertBytesToChar(0, nByte_2, nByte_3, nByte_4);
684                 }
685                 // wrong encoding ?
686                 else
687                 {
688                     throw new java.lang.Exception("Non well formed UTF-8 encoding.");
689                 }
690 
691                 sBuffer.append(nUTF8);
692                 // -> DEBUG !
693                 FileHelper.logEncodingData(sLog, nUTF8, nByteOrg_1, nByteOrg_2, nByteOrg_3, nByteOrg_4, nByte_1, nByte_2, nByte_3, nByte_4, nEncodingType);
694                 // <- DEBUG !
695             }
696         }
697 
698         }
699         catch(java.lang.Throwable ex)
700         {
701             // -> DEBUG !
702             FileHelper.logEncodingData(sLog, nUTF8, nByteOrg_1, nByteOrg_2, nByteOrg_3, nByteOrg_4, nByte_1, nByte_2, nByte_3, nByte_4, nEncodingType);
703 
704             java.io.File     aDir  = new java.io.File(aFile.getParent());
705             java.lang.String sDump = aFile.getName();
706             java.io.File     aDump = FileHelper.createUniqueFile(aDir, sDump, "dump");
707             FileHelper.writeEncodedBufferToFile(aDump, "UTF-8", false, sLog);
708             // <- DEBUG !
709 
710             java.lang.String sMsg = "File '"+aFile.getPath()+"' is not encoded right as UTF-8.";
711             throw new java.io.IOException(sMsg);
712         }
713 
714         aByteStream.close();
715     }
716 
717     //___________________________________________
718 
719     /** writes the given string buffer into the specified file
720      *  using the specified encoding.
721      *
722      *  Further it can be set, if the file should be expanded
723      *  or replaced by this new string buffer.
724      *
725      *  @param  aFile
726      *          must point to a system file. It can already exist!
727      *          e.g.: "c:\temp\test.txt"
728      *                "/tmp/test.txt"
729      *
730      *  @param  sEncoding
731      *          will be used to encode the string content inside the file.
732      *          e.g.: "UTF8"
733      *
734      *  @param  bAppend
735      *          specify if an already existing file will be
736      *          expanded or replaced.
737      *
738      *  @param  sBuffer
739      *          the new string content for this file.
740      */
writeEncodedBufferToFile(java.io.File aFile , java.lang.String sEncoding, boolean bAppend , java.lang.StringBuffer sBuffer )741     public static void writeEncodedBufferToFile(java.io.File           aFile    ,
742                                                 java.lang.String       sEncoding,
743                                                 boolean                bAppend  ,
744                                                 java.lang.StringBuffer sBuffer  )
745         throws java.io.IOException
746     {
747         java.io.FileOutputStream   aByteStream    = new java.io.FileOutputStream(aFile.getAbsolutePath(), bAppend);
748         java.io.OutputStreamWriter aEncodedWriter = new java.io.OutputStreamWriter(aByteStream, sEncoding);
749 
750         java.lang.String sTemp = sBuffer.toString();
751         aEncodedWriter.write(sTemp, 0, sTemp.length());
752 
753         aEncodedWriter.flush();
754         aEncodedWriter.close();
755 
756         if (!aFile.exists())
757             throw new java.io.IOException("File \""+aFile.getAbsolutePath()+"\" not written correctly.");
758     }
759 }
760