KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jahia > services > jef > JefFile


1 //
2
// ____.
3
// __/\ ______| |__/\. _______
4
// __ .____| | \ | +----+ \
5
// _______| /--| | | - \ _ | : - \_________
6
// \\______: :---| : : | : | \________>
7
// |__\---\_____________:______: :____|____:_____\
8
// /_____|
9
//
10
// . . . i n j a h i a w e t r u s t . . .
11
//
12

13 package org.jahia.services.jef;
14
15 import org.jahia.exceptions.JahiaException;
16
17 import javax.crypto.Cipher;
18 import javax.crypto.SecretKeyFactory;
19 import javax.crypto.spec.DESKeySpec;
20 import java.io.*;
21 import java.security.Key JavaDoc;
22 import java.security.Security JavaDoc;
23 import java.util.Enumeration JavaDoc;
24 import java.util.Hashtable JavaDoc;
25 import java.util.StringTokenizer JavaDoc;
26 import java.util.zip.CRC32 JavaDoc;
27
28
29 /**
30  * Load and extract data from a JEF file
31  *
32  * @author Khue Nguyen
33  * @version 1.0
34  */

35 class JefFile {
36     private static org.apache.log4j.Logger logger =
37             org.apache.log4j.Logger.getLogger (JecFile.class);
38
39     /** the full file path */
40     private String JavaDoc filePath = "";
41
42     /** the Hashtable of key values */
43     private Hashtable JavaDoc keys = new Hashtable JavaDoc ();
44
45     /** the Hashtable with the key = the filename and the value = the file content in a byte array. */
46     private Hashtable JavaDoc files = new Hashtable JavaDoc ();
47
48     private static final String JavaDoc CHAR_ENC = "UTF-16";
49
50     private final String JavaDoc MSG_INTERNAL_ERROR = "JefFile internal error";
51
52
53     //-------------------------------------------------------------------------
54
/**
55      * Construct a jef file object by extracting encrypted
56      * information out of the specified jef file.
57      *
58      * @param String the full path to the file
59      *
60      * @throws IOException when the file does not exist or on read error
61      * @throws InvalidJefException Throws this exception when the specified jef file is
62      * not valid.
63      * @throws JahiaException when a java security error occurs
64      */

65     public JefFile (String JavaDoc path)
66             throws IOException, InvalidJefFileException, JahiaException {
67
68         readFile (path);
69
70     }
71
72
73     //-------------------------------------------------------------------------
74
/**
75      * Return the hastable of keys
76      *
77      * @return Hashtable keys the hastables of keys
78      */

79     public final Hashtable JavaDoc getKeys () {
80         return keys;
81     }
82
83     //-------------------------------------------------------------------------
84
/**
85      * Return the key value
86      *
87      * @param String the key name
88      *
89      * @return String the key value as String
90      */

91     public final String JavaDoc getKey (String JavaDoc name) {
92         return (String JavaDoc) keys.get (name);
93     }
94
95
96     //-------------------------------------------------------------------------
97
/**
98      * Return the hastable of files
99      *
100      * @return Hashtable files, the hastables of files
101      */

102     public final Hashtable JavaDoc getFiles () {
103         return files;
104     }
105
106
107     //-------------------------------------------------------------------------
108
/**
109      * Return an enumaration of all filenames
110      *
111      * @return Hashtable files, the hastables of files
112      */

113     public final Enumeration JavaDoc getFilenames () {
114         return files.keys ();
115     }
116
117
118     //-------------------------------------------------------------------------
119
/**
120      * Save an extracted file to disk
121      *
122      * @param String filename, the filename of the file to save
123      * @param String dest, the destination file full path
124      *
125      * @return boolean true if successful
126      */

127     public final boolean extractFile (String JavaDoc filename, String JavaDoc dest) {
128
129         boolean result = true;
130
131         if (filename == null || dest == null) {
132             return false;
133         }
134
135         byte[] aFile = (byte[]) files.get (filename);
136
137         if (aFile == null) {
138             return false;
139         }
140
141         File f = new File (dest);
142
143 // write out the original file.
144
try {
145
146             FileOutputStream fos = new FileOutputStream (dest);
147
148             fos.write (aFile);
149
150 // flush the stream into the file and close the file
151
fos.flush ();
152             fos.close ();
153         } catch (FileNotFoundException ex) {
154             System.out.println ("ERROR : Could not create the encrypted file");
155             result = false;
156         } catch (SecurityException JavaDoc ex) {
157             System.out.println ("ERROR : No security permissions to create the file.");
158             result = false;
159         } catch (IOException ex) {
160             System.out.println ("ERROR : I/O error.");
161             result = false;
162         }
163
164         return result;
165     }
166
167
168     //-------------------------------------------------------------------------
169
/**
170      * Save all extracted files to disk in a gived directory
171      *
172      * @param String dest, the destination folder
173      *
174      * @return boolean true if successful
175      */

176     public final boolean extractFiles (String JavaDoc dest) {
177
178         boolean result = true;
179
180         if (dest == null) {
181             return false;
182         }
183
184
185         File f = new File (dest);
186         if (!f.isDirectory () || !f.canWrite ()) {
187             return false;
188         }
189
190         //logger.debug("extractFiles , dest = " + f.getAbsolutePath() );
191

192         Enumeration JavaDoc filenames = getFilenames ();
193         String JavaDoc filename = null;
194
195 // write out the original file.
196

197         while (filenames.hasMoreElements ()) {
198
199             filename = (String JavaDoc) filenames.nextElement ();
200
201             if (!extractFile (filename, dest + File.separator + filename)) {
202                 return false;
203             }
204         }
205
206         return result;
207     }
208
209
210     //-------------------------------------------------------------------------
211
/**
212      * Save all extracted at the current folder
213      *
214      * @return boolean true if successful
215      */

216     public final boolean extractFiles () {
217
218
219         boolean result = true;
220
221         File f = new File (filePath);
222         if (!f.isFile ()) {
223             return false;
224         }
225
226         return extractFiles (f.getParentFile ().getAbsolutePath ());
227
228     }
229
230
231     //-------------------------------------------------------------------------
232
/**
233      * Method getTokens : return an arrays of String tokens
234      *
235      * @param str the string to parse
236      * @param sep the separator
237      *
238      * @return an array of string values
239      *
240      * @author NK
241      */

242     private static String JavaDoc[] getTokens (String JavaDoc str, String JavaDoc sep) {
243         if (str == null) {
244             return null;
245         }
246
247         StringTokenizer JavaDoc st = new StringTokenizer JavaDoc (str, sep);
248         String JavaDoc[] result = new String JavaDoc[st.countTokens ()];
249         int count = 0;
250         while (st.hasMoreTokens ()) {
251             result[count] = st.nextToken ();
252             count++;
253         }
254
255         return result;
256     }
257
258
259     //-------------------------------------------------------------------------
260
/**
261      * parse the keys from a string like "key1=val1,key2=val2,key3=val3"
262      *
263      * @param String keysString the keys String to parse
264      *
265      * @return
266      */

267     private static Hashtable JavaDoc parseKeys (String JavaDoc keysString)
268             throws InvalidJefFileException {
269
270         Hashtable JavaDoc keys = new Hashtable JavaDoc ();
271
272         if (keysString == null || keysString.trim ().equals ("")) {
273             throw new InvalidJefFileException ("invalid keys values");
274         }
275
276         //logger.debug(" parseKeys keyString = " + keysString);
277

278         String JavaDoc k = "";
279         String JavaDoc val = "";
280
281         String JavaDoc[] tokens = getTokens (keysString, ",");
282         for (int i = 0; i < tokens.length; i++) {
283             if ((tokens[i].indexOf ("=") == -1) || tokens[i].indexOf ("=") == (tokens[i].length () - 1)) {
284                 throw new InvalidJefFileException ("invalid keys values");
285             }
286             k = tokens[i].substring (0, tokens[i].indexOf ("="));
287             val = tokens[i].substring (tokens[i].indexOf ("=") + 1, tokens[i].length ());
288             //logger.debug(" found key: name = " + k + ", val = " + val);
289
keys.put (k.trim (), val.trim ());
290         }
291
292         return keys;
293     }
294
295
296
297     //-------------------------------------------------------------------------
298
/**
299      * Read the encrypted file
300      *
301      * @param String the path to the file
302      */

303     private final void readFile (String JavaDoc path)
304             throws IOException, InvalidJefFileException, JahiaException {
305
306
307         FileInputStream fstream = null;
308         DataInputStream stream = null;
309         ByteArrayOutputStream bos = null;
310         ByteArrayInputStream byteStream = null;
311
312         try {
313
314 // open the file
315
File srcFile = new File (path);
316
317             if (!srcFile.exists () || !srcFile.canRead ()) {
318                 logger.debug ("cannot access file " + path);
319                 throw new JahiaException (MSG_INTERNAL_ERROR, "cannot access file " + path,
320                         JefFileConstants.IO_ERROR, JahiaException.ERROR_SEVERITY);
321
322             }
323
324
325             filePath = path;
326
327             boolean securityErr = false;
328             boolean tryAgain = true;
329             boolean goSleep = false;
330             long fLength = 0;
331
332             long storedChecksum = 0;
333             long streamChecksum = -1;
334
335             byte[] bytes = null;
336             byte[] data = null;
337
338             while (tryAgain) { // try again if there is an error
339
// due to the fact that the file is still modified
340

341                 securityErr = false;
342                 fLength = srcFile.length ();
343                 goSleep = false;
344
345                 try {
346
347                     fstream = new FileInputStream (srcFile);
348                     stream = new DataInputStream (fstream);
349
350                     // create the raw byte stream from the file size by removing the
351
// checksum bytes (long=8bytes), the Cipher secret key(int=4bytes) and the offset(short=4bytes)
352
int streamSize = (new Long JavaDoc (srcFile.length () - 16)).intValue ();
353                     bos = new ByteArrayOutputStream ();
354                     byte[] buff = null;
355                     int crcOffset = stream.readInt ();
356
357                     //logger.debug("offset " + crcOffset);
358

359                     buff = new byte[crcOffset];
360                     stream.read (buff, 0, crcOffset);
361                     bos.write (buff);
362
363
364                     // int the Cipher
365
Security.addProvider (
366                             new com.sun.crypto.provider.SunJCE ());
367
368                     // get the secret key
369
int keyLength = stream.readInt ();
370                     byte[] keyAsBytes = new byte[keyLength];
371                     stream.read (keyAsBytes);
372
373                     DESKeySpec keySpec = new DESKeySpec (keyAsBytes);
374
375                     Key JavaDoc myKey = SecretKeyFactory.getInstance ("DES").generateSecret (keySpec);
376                     keyAsBytes = myKey.getEncoded ();
377                     //logger.debug(" Cipher secret key = "+ new String(keyAsBytes) );
378

379                     Cipher decCipher = Cipher.getInstance ("DES");
380
381
382                     decCipher.init (Cipher.DECRYPT_MODE, myKey);
383
384
385                     storedChecksum = stream.readLong ();
386                     /*
387 logger.debug(" stored checksum = "+Long.toHexString (storedChecksum));
388                     */

389                     buff = new byte[streamSize - (crcOffset + keyLength)];
390                     stream.read (buff, 0, buff.length);
391                     bos.write (buff);
392                     buff = null;
393
394                     bytes = bos.toByteArray ();
395
396                     // free memory of unused objects
397
fstream.close ();
398                     stream = null;
399                     fstream = null;
400                     srcFile = null;
401                     bos.close ();
402                     bos = null;
403
404
405                     // compute the stream CRC
406
CRC32 JavaDoc crc = new CRC32 JavaDoc ();
407                     crc.update (bytes);
408
409                     streamChecksum = crc.getValue ();
410                     /*
411 logger.debug(" stream checksum = "+Long.toHexString (streamChecksum));
412                     */

413                     //logger.debug(" data stream length before Cipher decryption " + bytes.length );
414

415                     byte[] decryptedBytes = decCipher.doFinal (bytes);
416
417                     bytes = null;
418
419                     //logger.debug(" data stream length after Cipher decryption " + decryptedBytes.length );
420

421
422                     if (srcFile == null) {
423                         srcFile = new File (path);
424                     }
425
426                     if (fLength == srcFile.length ()) {
427                         if ((streamChecksum != storedChecksum)) {
428                             logger.debug (" checksum not match ");
429                             throw new InvalidJefFileException ();
430                         }
431
432                         byteStream = new ByteArrayInputStream (decryptedBytes);
433                         stream = new DataInputStream (byteStream);
434                         int offset = 0;
435                         int totalOffset = offset;
436
437                         //logger.debug("Jahia Encrypted File Info :");
438

439
440                         // extract keys value
441
offset = stream.readShort ();
442                         totalOffset += offset;
443
444                         //logger.debug("keys nb char: " + offset);
445

446                         byte[] chars = new byte[offset];
447
448                         if (offset > 0) {
449                             stream.read (chars, 0, offset);
450                             String JavaDoc keysString = new String JavaDoc (chars, CHAR_ENC);
451                             //logger.debug("keys : " + keys);
452
keys = parseKeys (keysString);
453                         } else {
454                             //logger.debug("no keys values");
455
}
456
457                         //Extract the file content
458
data = new byte[decryptedBytes.length - (totalOffset + 2)];
459
460                         stream.read (data, 0, data.length);
461
462                         //logger.debug("files nb byte = " + data.length);
463

464                         // extract the encrypted files
465
byteStream = new ByteArrayInputStream (data);
466                         stream = new DataInputStream (byteStream);
467
468                         int nbBytes = data.length;
469                         int nbBytesRead = 0;
470                         offset = 0;
471                         String JavaDoc fileName = "";
472                         Long JavaDoc fSize = null;
473                         byte[] aFile = null;
474
475                         while (nbBytesRead < nbBytes) {
476
477                             // extract the filename
478
offset = stream.readShort ();
479                             nbBytesRead += 2;
480                             chars = new byte[offset];
481                             nbBytesRead += offset;
482
483                             stream.read (chars, 0, offset);
484                             fileName = new String JavaDoc (chars, CHAR_ENC);
485                             //logger.debug(" read encryted file " + fileName + "\n");
486

487                             // extract the file size
488
fSize = new Long JavaDoc (stream.readLong ());
489
490                             //logger.debug(" size " +fSize + "\n");
491

492                             aFile = new byte[fSize.intValue ()];
493
494                             nbBytesRead += 8;
495
496                             stream.read (aFile, 0, fSize.intValue ());
497                             nbBytesRead += fSize.intValue ();
498
499                             files.put (fileName, aFile);
500                             aFile = null;
501
502                             //logger.debug(" nb bytes read " + nbBytesRead + "\n");
503
}
504
505                         if (fLength == srcFile.length ()) {
506                             tryAgain = false;
507                         }
508                     } else {
509                         goSleep = true;
510                     }
511                     bytes = null;
512                     data = null;
513
514                 } catch (java.security.InvalidKeyException JavaDoc ike) {
515                     securityErr = true;
516                     logger.error (" exception occured " + ike.getMessage ());
517                     ike.printStackTrace ();
518                     throw new JahiaException (MSG_INTERNAL_ERROR, "JefFile , security exception"
519                             + ike.getMessage (),
520                             JefFileConstants.JAVA_SECURITY_ERROR,
521                             JahiaException.ERROR_SEVERITY);
522                 } catch (java.security.NoSuchAlgorithmException JavaDoc nae) {
523                     securityErr = true;
524                     logger.error (" exception occured " + nae.getMessage ());
525                     nae.printStackTrace ();
526                     throw new JahiaException (MSG_INTERNAL_ERROR, "JefFile , security exception"
527                             + nae.getMessage (),
528                             JefFileConstants.JAVA_SECURITY_ERROR,
529                             JahiaException.ERROR_SEVERITY);
530                 } catch (java.security.spec.InvalidKeySpecException JavaDoc iks) {
531                     securityErr = true;
532                     logger.error (" exception occured " + iks.getMessage ());
533                     iks.printStackTrace ();
534                     throw new JahiaException (MSG_INTERNAL_ERROR, "JefFile , security exception"
535                             + iks.getMessage (),
536                             JefFileConstants.JAVA_SECURITY_ERROR,
537                             JahiaException.ERROR_SEVERITY);
538                 } catch (javax.crypto.NoSuchPaddingException npe) {
539                     securityErr = true;
540                     logger.error (" exception occured " + npe.getMessage ());
541                     npe.printStackTrace ();
542                     throw new JahiaException (MSG_INTERNAL_ERROR, "JefFile , security exception"
543                             + npe.getMessage (),
544                             JefFileConstants.JAVA_SECURITY_ERROR,
545                             JahiaException.ERROR_SEVERITY);
546                 } catch (javax.crypto.IllegalBlockSizeException ibse) {
547                     securityErr = true;
548                     logger.error (" exception occured " + ibse.getMessage ());
549                     ibse.printStackTrace ();
550                     throw new JahiaException (MSG_INTERNAL_ERROR, "JefFile , security exception"
551                             + ibse.getMessage (),
552                             JefFileConstants.JAVA_SECURITY_ERROR,
553                             JahiaException.ERROR_SEVERITY);
554                 } catch (javax.crypto.BadPaddingException bpe) {
555                     securityErr = true;
556                     logger.error (" exception occured " + bpe.getMessage ());
557                     bpe.printStackTrace ();
558                     throw new JahiaException (MSG_INTERNAL_ERROR, "JefFile , security exception"
559                             + bpe.getMessage (),
560                             JefFileConstants.JAVA_SECURITY_ERROR,
561                             JahiaException.ERROR_SEVERITY);
562                 } catch (java.lang.ExceptionInInitializerError JavaDoc eiie) {
563                     securityErr = true;
564                     logger.error (" exception occured " + eiie.getMessage ());
565                     eiie.printStackTrace ();
566                     throw new JahiaException (MSG_INTERNAL_ERROR, "JefFile , java.lang.ExceptionInInitializerError "
567                             + eiie.getMessage (),
568                             JefFileConstants.JAVA_SECURITY_ERROR,
569                             JahiaException.ERROR_SEVERITY);
570                 } catch (IOException ioe) {
571                     logger.error (" exception occured " + ioe.getMessage ());
572                     ioe.printStackTrace ();
573                     if (srcFile.isFile () && srcFile.canRead () && (fLength == srcFile.length ())) {
574                         File tmpFile = new File (srcFile.getAbsolutePath () + "_error");
575                         srcFile.renameTo (tmpFile);
576                         tryAgain = false;
577                         throw new JahiaException (MSG_INTERNAL_ERROR, "JefFile , IOException "
578                                 + ioe.getMessage (),
579                                 JefFileConstants.IO_ERROR, JahiaException.ERROR_SEVERITY);
580                     } else {
581                         goSleep = true;
582                     }
583                 } catch (Throwable JavaDoc t) {
584                     logger.error (" exception occured " + t.getMessage ());
585                     t.printStackTrace ();
586                     if (srcFile.isFile () && srcFile.canRead () && (fLength == srcFile.length ())) {
587                         //File tmpFile = new File(srcFile.getAbsolutePath() + "_error");
588
//srcFile.renameTo(tmpFile);
589
tryAgain = false;
590                         throw new JahiaException (MSG_INTERNAL_ERROR, "JefFile , Unknown Exception ",
591                                 JefFileConstants.UNKNOWN_ERROR, JahiaException.ERROR_SEVERITY);
592                     } else {
593                         goSleep = true;
594                     }
595                 }
596
597                 if (goSleep) {
598                     try {
599                         // wait while the file is still modified
600
//logger.debug(" go to sleep1 , file length=" + fLength);
601
Thread.sleep (500);
602                         while (fLength < srcFile.length ()) {
603                             fLength = srcFile.length ();
604                             //logger.debug(" go to sleep2 , file length=" + fLength);
605
Thread.sleep (500);
606                         }
607                     } catch (Throwable JavaDoc tr) {
608                         logger.error (tr.getMessage ());
609                     }
610                 }
611             }
612
613         } finally {
614
615
616             if (byteStream != null) {
617                 byteStream.close ();
618             }
619             byteStream = null;
620
621
622             if (stream != null) {
623                 stream.close ();
624             }
625             stream = null;
626
627
628             if (fstream != null) {
629                 fstream.close ();
630             }
631             fstream = null;
632
633
634             if (bos != null) {
635                 bos.close ();
636             }
637             bos = null;
638
639         }
640
641     }
642
643 }
644
645
Popular Tags