1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.util;
24  
25  import com.liferay.portal.kernel.log.Log;
26  import com.liferay.portal.kernel.log.LogFactoryUtil;
27  import com.liferay.portal.kernel.util.ByteArrayMaker;
28  import com.liferay.portal.kernel.util.FileComparator;
29  import com.liferay.portal.kernel.util.GetterUtil;
30  import com.liferay.portal.kernel.util.StringPool;
31  import com.liferay.portal.kernel.util.StringUtil;
32  import com.liferay.portal.kernel.util.Time;
33  import com.liferay.portal.kernel.util.Validator;
34  import com.liferay.util.PwdGenerator;
35  import com.liferay.util.SystemProperties;
36  import com.liferay.util.lucene.JerichoHTMLTextExtractor;
37  
38  import java.io.BufferedInputStream;
39  import java.io.BufferedReader;
40  import java.io.BufferedWriter;
41  import java.io.File;
42  import java.io.FileInputStream;
43  import java.io.FileOutputStream;
44  import java.io.FileReader;
45  import java.io.IOException;
46  import java.io.InputStream;
47  import java.io.OutputStreamWriter;
48  import java.io.Reader;
49  
50  import java.nio.channels.FileChannel;
51  
52  import java.util.ArrayList;
53  import java.util.Arrays;
54  import java.util.List;
55  import java.util.Properties;
56  
57  import org.apache.jackrabbit.extractor.MsExcelTextExtractor;
58  import org.apache.jackrabbit.extractor.MsPowerPointTextExtractor;
59  import org.apache.jackrabbit.extractor.MsWordTextExtractor;
60  import org.apache.jackrabbit.extractor.OpenOfficeTextExtractor;
61  import org.apache.jackrabbit.extractor.PdfTextExtractor;
62  import org.apache.jackrabbit.extractor.PlainTextExtractor;
63  import org.apache.jackrabbit.extractor.RTFTextExtractor;
64  import org.apache.jackrabbit.extractor.TextExtractor;
65  import org.apache.jackrabbit.extractor.XMLTextExtractor;
66  
67  import org.mozilla.intl.chardet.nsDetector;
68  import org.mozilla.intl.chardet.nsPSMDetector;
69  
70  /**
71   * <a href="FileImpl.java.html"><b><i>View Source</i></b></a>
72   *
73   * @author Brian Wing Shun Chan
74   * @author Alexander Chow
75   *
76   */
77  public class FileImpl implements com.liferay.portal.kernel.util.File {
78  
79      public static FileImpl getInstance() {
80          return _instance;
81      }
82  
83      public void copyDirectory(String sourceDirName, String destinationDirName) {
84          copyDirectory(new File(sourceDirName), new File(destinationDirName));
85      }
86  
87      public void copyDirectory(File source, File destination) {
88          if (source.exists() && source.isDirectory()) {
89              if (!destination.exists()) {
90                  destination.mkdirs();
91              }
92  
93              File[] fileArray = source.listFiles();
94  
95              for (int i = 0; i < fileArray.length; i++) {
96                  if (fileArray[i].isDirectory()) {
97                      copyDirectory(
98                          fileArray[i],
99                          new File(destination.getPath() + File.separator
100                             + fileArray[i].getName()));
101                 }
102                 else {
103                     copyFile(
104                         fileArray[i],
105                         new File(destination.getPath() + File.separator
106                             + fileArray[i].getName()));
107                 }
108             }
109         }
110     }
111 
112     public void copyFile(String source, String destination) {
113         copyFile(source, destination, false);
114     }
115 
116     public void copyFile(String source, String destination, boolean lazy) {
117         copyFile(new File(source), new File(destination), lazy);
118     }
119 
120     public void copyFile(File source, File destination) {
121         copyFile(source, destination, false);
122     }
123 
124     public void copyFile(File source, File destination, boolean lazy) {
125         if (!source.exists()) {
126             return;
127         }
128 
129         if (lazy) {
130             String oldContent = null;
131 
132             try {
133                 oldContent = read(source);
134             }
135             catch (Exception e) {
136                 return;
137             }
138 
139             String newContent = null;
140 
141             try {
142                 newContent = read(destination);
143             }
144             catch (Exception e) {
145             }
146 
147             if ((oldContent == null) || !oldContent.equals(newContent)) {
148                 copyFile(source, destination, false);
149             }
150         }
151         else {
152             if ((destination.getParentFile() != null) &&
153                 (!destination.getParentFile().exists())) {
154 
155                 destination.getParentFile().mkdirs();
156             }
157 
158             try {
159                 FileChannel srcChannel =
160                     new FileInputStream(source).getChannel();
161                 FileChannel dstChannel =
162                     new FileOutputStream(destination).getChannel();
163 
164                 dstChannel.transferFrom(srcChannel, 0, srcChannel.size());
165 
166                 srcChannel.close();
167                 dstChannel.close();
168             }
169             catch (IOException ioe) {
170                 _log.error(ioe.getMessage());
171             }
172         }
173     }
174 
175     public File createTempFile() {
176         return createTempFile(null);
177     }
178 
179     public File createTempFile(String extension) {
180         return new File(createTempFileName(extension));
181     }
182 
183     public String createTempFileName() {
184         return createTempFileName(null);
185     }
186 
187     public String createTempFileName(String extension) {
188         StringBuilder sb = new StringBuilder();
189 
190         sb.append(SystemProperties.get(SystemProperties.TMP_DIR));
191         sb.append(StringPool.SLASH);
192         sb.append(Time.getTimestamp());
193         sb.append(PwdGenerator.getPassword(PwdGenerator.KEY2, 8));
194 
195         if (Validator.isNotNull(extension)) {
196             sb.append(StringPool.PERIOD);
197             sb.append(extension);
198         }
199 
200         return sb.toString();
201     }
202 
203     public boolean delete(String file) {
204         return delete(new File(file));
205     }
206 
207     public boolean delete(File file) {
208         if ((file != null) && file.exists()) {
209             return file.delete();
210         }
211         else {
212             return false;
213         }
214     }
215 
216     public void deltree(String directory) {
217         deltree(new File(directory));
218     }
219 
220     public void deltree(File directory) {
221         if (directory.exists() && directory.isDirectory()) {
222             File[] fileArray = directory.listFiles();
223 
224             for (int i = 0; i < fileArray.length; i++) {
225                 if (fileArray[i].isDirectory()) {
226                     deltree(fileArray[i]);
227                 }
228                 else {
229                     fileArray[i].delete();
230                 }
231             }
232 
233             directory.delete();
234         }
235     }
236 
237     public boolean exists(String fileName) {
238         return exists(new File(fileName));
239     }
240 
241     public boolean exists(File file) {
242         return file.exists();
243     }
244 
245     public String extractText(InputStream is, String fileExt) {
246         String text = null;
247 
248         try {
249             fileExt = GetterUtil.getString(fileExt).toLowerCase();
250 
251             TextExtractor extractor = null;
252 
253             String contentType = null;
254             String encoding = System.getProperty("encoding");
255 
256             if (fileExt.equals(".doc")) {
257                 extractor = new MsWordTextExtractor();
258 
259                 contentType = "application/vnd.ms-word";
260             }
261             else if (fileExt.equals(".htm") || fileExt.equals(".html")) {
262                 extractor = new JerichoHTMLTextExtractor();
263 
264                 contentType = "text/html";
265             }
266             else if (fileExt.equals(".odb") || fileExt.equals(".odf") ||
267                      fileExt.equals(".odg") || fileExt.equals(".odp") ||
268                      fileExt.equals(".ods") || fileExt.equals(".odt")) {
269 
270                 extractor = new OpenOfficeTextExtractor();
271 
272                 contentType = "application/vnd.oasis.opendocument.";
273 
274                 if (fileExt.equals(".odb")) {
275                     contentType += "database";
276                 }
277                 else if (fileExt.equals(".odf")) {
278                     contentType += "formula";
279                 }
280                 else if (fileExt.equals(".odg")) {
281                     contentType += "graphics";
282                 }
283                 else if (fileExt.equals(".odp")) {
284                     contentType += "presentation";
285                 }
286                 else if (fileExt.equals(".ods")) {
287                     contentType += "spreadsheet";
288                 }
289                 else if (fileExt.equals(".odt")) {
290                     contentType += "text";
291                 }
292             }
293             else if (fileExt.equals(".pdf")) {
294                 extractor = new PdfTextExtractor();
295 
296                 contentType = "application/pdf";
297             }
298             else if (fileExt.equals(".ppt")) {
299                 extractor = new MsPowerPointTextExtractor();
300 
301                 contentType = "application/vnd.ms-powerpoint";
302             }
303             else if (fileExt.equals(".rtf")) {
304                 extractor = new RTFTextExtractor();
305 
306                 contentType = "application/rtf";
307             }
308             else if (fileExt.equals(".txt")) {
309                 extractor = new PlainTextExtractor();
310 
311                 contentType = "text/plain";
312             }
313             else if (fileExt.equals(".xls")) {
314                 extractor = new MsExcelTextExtractor();
315 
316                 contentType = "application/vnd.ms-excel";
317             }
318             else if (fileExt.equals(".xml")) {
319                 extractor = new XMLTextExtractor();
320 
321                 contentType = "text/xml";
322             }
323 
324             if (extractor != null) {
325                 if (_log.isInfoEnabled()) {
326                     _log.info(
327                         "Using extractor " + extractor.getClass().getName() +
328                             " for extension " + fileExt);
329                 }
330 
331                 StringBuilder sb = new StringBuilder();
332 
333                 BufferedReader reader = new BufferedReader(
334                     extractor.extractText(is, contentType, encoding));
335 
336                 int i;
337 
338                 while ((i = reader.read()) != -1) {
339                     sb.append((char)i);
340                 }
341 
342                 reader.close();
343 
344                 text = sb.toString();
345             }
346             else {
347                 if (_log.isInfoEnabled()) {
348                     _log.info("No extractor found for extension " + fileExt);
349                 }
350             }
351         }
352         catch (Exception e) {
353             _log.error(e);
354         }
355 
356         if (_log.isDebugEnabled()) {
357             _log.debug("Extractor returned text:\n\n" + text);
358         }
359 
360         if (text == null) {
361             text = StringPool.BLANK;
362         }
363 
364         return text;
365     }
366 
367     public String getAbsolutePath(File file) {
368         return StringUtil.replace(
369             file.getAbsolutePath(), StringPool.BACK_SLASH, StringPool.SLASH);
370     }
371 
372     public byte[] getBytes(File file) throws IOException {
373         if ((file == null) || !file.exists()) {
374             return null;
375         }
376 
377         FileInputStream is = new FileInputStream(file);
378 
379         byte[] bytes = getBytes(is, (int)file.length());
380 
381         is.close();
382 
383         return bytes;
384     }
385 
386     public byte[] getBytes(InputStream is) throws IOException {
387         return getBytes(is, -1);
388     }
389 
390     public byte[] getBytes(InputStream is, int bufferSize) throws IOException {
391         ByteArrayMaker bam = null;
392 
393         if (bufferSize <= 0) {
394             bam = new ByteArrayMaker();
395         }
396         else {
397             bam = new ByteArrayMaker(bufferSize);
398         }
399 
400         boolean createBuffered = false;
401 
402         try {
403             if (!(is instanceof BufferedInputStream)) {
404                 is = new BufferedInputStream(is);
405 
406                 createBuffered = true;
407             }
408 
409             int c = is.read();
410 
411             while (c != -1) {
412                 bam.write(c);
413 
414                 c = is.read();
415             }
416         }
417         finally {
418             if (createBuffered) {
419                 is.close();
420             }
421         }
422 
423         bam.close();
424 
425         return bam.toByteArray();
426     }
427 
428     public String getExtension(String fileName) {
429         if (fileName == null) {
430             return null;
431         }
432 
433         int pos = fileName.lastIndexOf(StringPool.PERIOD);
434 
435         if (pos != -1) {
436             return fileName.substring(pos + 1, fileName.length()).toLowerCase();
437         }
438         else {
439             return null;
440         }
441     }
442 
443     public String getPath(String fullFileName) {
444         int pos = fullFileName.lastIndexOf(StringPool.SLASH);
445 
446         if (pos == -1) {
447             pos = fullFileName.lastIndexOf(StringPool.BACK_SLASH);
448         }
449 
450         String shortFileName = fullFileName.substring(0, pos);
451 
452         if (Validator.isNull(shortFileName)) {
453             return StringPool.SLASH;
454         }
455 
456         return shortFileName;
457     }
458 
459     public String getShortFileName(String fullFileName) {
460         int pos = fullFileName.lastIndexOf(StringPool.SLASH);
461 
462         if (pos == -1) {
463             pos = fullFileName.lastIndexOf(StringPool.BACK_SLASH);
464         }
465 
466         String shortFileName =
467             fullFileName.substring(pos + 1, fullFileName.length());
468 
469         return shortFileName;
470     }
471 
472     public boolean isAscii(File file) throws IOException {
473         boolean ascii = true;
474 
475         nsDetector detector = new nsDetector(nsPSMDetector.ALL);
476 
477         BufferedInputStream bis = new BufferedInputStream(
478             new FileInputStream(file));
479 
480         byte[] buffer = new byte[1024];
481 
482         int len = 0;
483 
484         while ((len = bis.read(buffer, 0, buffer.length)) != -1) {
485             if (ascii) {
486                 ascii = detector.isAscii(buffer, len);
487 
488                 if (!ascii) {
489                     break;
490                 }
491             }
492         }
493 
494         detector.DataEnd();
495 
496         return ascii;
497     }
498 
499     public String[] listDirs(String fileName) {
500         return listDirs(new File(fileName));
501     }
502 
503     public String[] listDirs(File file) {
504         List<String> dirs = new ArrayList<String>();
505 
506         File[] fileArray = file.listFiles();
507 
508         for (int i = 0; (fileArray != null) && (i < fileArray.length); i++) {
509             if (fileArray[i].isDirectory()) {
510                 dirs.add(fileArray[i].getName());
511             }
512         }
513 
514         return dirs.toArray(new String[dirs.size()]);
515     }
516 
517     public String[] listFiles(String fileName) {
518         if (Validator.isNull(fileName)) {
519             return new String[0];
520         }
521 
522         return listFiles(new File(fileName));
523     }
524 
525     public String[] listFiles(File file) {
526         List<String> files = new ArrayList<String>();
527 
528         File[] fileArray = file.listFiles();
529 
530         for (int i = 0; (fileArray != null) && (i < fileArray.length); i++) {
531             if (fileArray[i].isFile()) {
532                 files.add(fileArray[i].getName());
533             }
534         }
535 
536         return files.toArray(new String[files.size()]);
537     }
538 
539     public void mkdirs(String pathName) {
540         File file = new File(pathName);
541 
542         file.mkdirs();
543     }
544 
545     public boolean move(String sourceFileName, String destinationFileName) {
546         return move(new File(sourceFileName), new File(destinationFileName));
547     }
548 
549     public boolean move(File source, File destination) {
550         if (!source.exists()) {
551             return false;
552         }
553 
554         destination.delete();
555 
556         return source.renameTo(destination);
557     }
558 
559     public String read(String fileName) throws IOException {
560         return read(new File(fileName));
561     }
562 
563     public String read(File file) throws IOException {
564         return read(file, false);
565     }
566 
567     public String read(File file, boolean raw) throws IOException {
568         FileInputStream fis = new FileInputStream(file);
569 
570         byte[] bytes = new byte[fis.available()];
571 
572         fis.read(bytes);
573 
574         fis.close();
575 
576         String s = new String(bytes, StringPool.UTF8);
577 
578         if (raw) {
579             return s;
580         }
581         else {
582             return StringUtil.replace(
583                 s, StringPool.RETURN_NEW_LINE, StringPool.NEW_LINE);
584         }
585     }
586 
587     public String replaceSeparator(String fileName) {
588         return StringUtil.replace(
589             fileName, StringPool.BACK_SLASH, StringPool.SLASH);
590     }
591 
592     public File[] sortFiles(File[] files) {
593         if (files == null) {
594             return null;
595         }
596 
597         Arrays.sort(files, new FileComparator());
598 
599         List<File> directoryList = new ArrayList<File>();
600         List<File> fileList = new ArrayList<File>();
601 
602         for (int i = 0; i < files.length; i++) {
603             if (files[i].isDirectory()) {
604                 directoryList.add(files[i]);
605             }
606             else {
607                 fileList.add(files[i]);
608             }
609         }
610 
611         directoryList.addAll(fileList);
612 
613         return directoryList.toArray(new File[directoryList.size()]);
614     }
615 
616     public String stripExtension(String fileName) {
617         if (fileName == null) {
618             return null;
619         }
620 
621         int pos = fileName.lastIndexOf(StringPool.PERIOD);
622 
623         if (pos != -1) {
624             return fileName.substring(0, pos);
625         }
626         else {
627             return fileName;
628         }
629     }
630 
631     public List<String> toList(Reader reader) {
632         List<String> list = new ArrayList<String>();
633 
634         try {
635             BufferedReader br = new BufferedReader(reader);
636 
637             String line = null;
638 
639             while ((line = br.readLine()) != null) {
640                 list.add(line);
641             }
642 
643             br.close();
644         }
645         catch (IOException ioe) {
646         }
647 
648         return list;
649     }
650 
651     public List<String> toList(String fileName) {
652         try {
653             return toList(new FileReader(fileName));
654         }
655         catch (IOException ioe) {
656             return new ArrayList<String>();
657         }
658     }
659 
660     public Properties toProperties(FileInputStream fis) {
661         Properties props = new Properties();
662 
663         try {
664             props.load(fis);
665         }
666         catch (IOException ioe) {
667         }
668 
669         return props;
670     }
671 
672     public Properties toProperties(String fileName) {
673         try {
674             return toProperties(new FileInputStream(fileName));
675         }
676         catch (IOException ioe) {
677             return new Properties();
678         }
679     }
680 
681     public void write(String fileName, String s) throws IOException {
682         write(new File(fileName), s);
683     }
684 
685     public void write(String fileName, String s, boolean lazy)
686         throws IOException {
687 
688         write(new File(fileName), s, lazy);
689     }
690 
691     public void write(String fileName, String s, boolean lazy, boolean append)
692         throws IOException {
693 
694         write(new File(fileName), s, lazy, append);
695     }
696 
697     public void write(String pathName, String fileName, String s)
698         throws IOException {
699 
700         write(new File(pathName, fileName), s);
701     }
702 
703     public void write(String pathName, String fileName, String s, boolean lazy)
704         throws IOException {
705 
706         write(new File(pathName, fileName), s, lazy);
707     }
708 
709     public void write(
710             String pathName, String fileName, String s, boolean lazy,
711             boolean append)
712         throws IOException {
713 
714         write(new File(pathName, fileName), s, lazy, append);
715     }
716 
717     public void write(File file, String s) throws IOException {
718         write(file, s, false);
719     }
720 
721     public void write(File file, String s, boolean lazy)
722         throws IOException {
723 
724         write(file, s, lazy, false);
725     }
726 
727     public void write(File file, String s, boolean lazy, boolean append)
728         throws IOException {
729 
730         if (file.getParent() != null) {
731             mkdirs(file.getParent());
732         }
733 
734         if (lazy && file.exists()) {
735             String content = read(file);
736 
737             if (content.equals(s)) {
738                 return;
739             }
740         }
741 
742         BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
743             new FileOutputStream(file, append), StringPool.UTF8));
744 
745         bw.write(s);
746 
747         bw.close();
748     }
749 
750     public void write(String fileName, byte[] bytes) throws IOException {
751         write(new File(fileName), bytes);
752     }
753 
754     public void write(File file, byte[] bytes) throws IOException {
755         if (file.getParent() != null) {
756             mkdirs(file.getParent());
757         }
758 
759         FileOutputStream fos = new FileOutputStream(file);
760 
761         fos.write(bytes);
762 
763         fos.close();
764     }
765 
766     public void write(String fileName, InputStream is) throws IOException {
767         write(fileName, getBytes(is));
768     }
769 
770     public void write(File file, InputStream is) throws IOException {
771         write(file, getBytes(is));
772     }
773 
774     private static Log _log = LogFactoryUtil.getLog(FileImpl.class);
775 
776     private static FileImpl _instance = new FileImpl();
777 
778 }