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         StringBuilder sb = new StringBuilder();
181 
182         sb.append(SystemProperties.get(SystemProperties.TMP_DIR));
183         sb.append(StringPool.SLASH);
184         sb.append(Time.getTimestamp());
185         sb.append(PwdGenerator.getPassword(PwdGenerator.KEY2, 8));
186 
187         if (Validator.isNotNull(extension)) {
188             sb.append(StringPool.PERIOD);
189             sb.append(extension);
190         }
191 
192         return new File(sb.toString());
193     }
194 
195     public boolean delete(String file) {
196         return delete(new File(file));
197     }
198 
199     public boolean delete(File file) {
200         if (file.exists()) {
201             return file.delete();
202         }
203         else {
204             return false;
205         }
206     }
207 
208     public void deltree(String directory) {
209         deltree(new File(directory));
210     }
211 
212     public void deltree(File directory) {
213         if (directory.exists() && directory.isDirectory()) {
214             File[] fileArray = directory.listFiles();
215 
216             for (int i = 0; i < fileArray.length; i++) {
217                 if (fileArray[i].isDirectory()) {
218                     deltree(fileArray[i]);
219                 }
220                 else {
221                     fileArray[i].delete();
222                 }
223             }
224 
225             directory.delete();
226         }
227     }
228 
229     public boolean exists(String fileName) {
230         return exists(new File(fileName));
231     }
232 
233     public boolean exists(File file) {
234         return file.exists();
235     }
236 
237     public String extractText(InputStream is, String fileExt) {
238         String text = null;
239 
240         try {
241             fileExt = GetterUtil.getString(fileExt).toLowerCase();
242 
243             TextExtractor extractor = null;
244 
245             String contentType = null;
246             String encoding = System.getProperty("encoding");
247 
248             if (fileExt.equals(".doc")) {
249                 extractor = new MsWordTextExtractor();
250 
251                 contentType = "application/vnd.ms-word";
252             }
253             else if (fileExt.equals(".htm") || fileExt.equals(".html")) {
254                 extractor = new JerichoHTMLTextExtractor();
255 
256                 contentType = "text/html";
257             }
258             else if (fileExt.equals(".odb") || fileExt.equals(".odf") ||
259                      fileExt.equals(".odg") || fileExt.equals(".odp") ||
260                      fileExt.equals(".ods") || fileExt.equals(".odt")) {
261 
262                 extractor = new OpenOfficeTextExtractor();
263 
264                 contentType = "application/vnd.oasis.opendocument.";
265 
266                 if (fileExt.equals(".odb")) {
267                     contentType += "database";
268                 }
269                 else if (fileExt.equals(".odf")) {
270                     contentType += "formula";
271                 }
272                 else if (fileExt.equals(".odg")) {
273                     contentType += "graphics";
274                 }
275                 else if (fileExt.equals(".odp")) {
276                     contentType += "presentation";
277                 }
278                 else if (fileExt.equals(".ods")) {
279                     contentType += "spreadsheet";
280                 }
281                 else if (fileExt.equals(".odt")) {
282                     contentType += "text";
283                 }
284             }
285             else if (fileExt.equals(".pdf")) {
286                 extractor = new PdfTextExtractor();
287 
288                 contentType = "application/pdf";
289             }
290             else if (fileExt.equals(".ppt")) {
291                 extractor = new MsPowerPointTextExtractor();
292 
293                 contentType = "application/vnd.ms-powerpoint";
294             }
295             else if (fileExt.equals(".rtf")) {
296                 extractor = new RTFTextExtractor();
297 
298                 contentType = "application/rtf";
299             }
300             else if (fileExt.equals(".txt")) {
301                 extractor = new PlainTextExtractor();
302 
303                 contentType = "text/plain";
304             }
305             else if (fileExt.equals(".xls")) {
306                 extractor = new MsExcelTextExtractor();
307 
308                 contentType = "application/vnd.ms-excel";
309             }
310             else if (fileExt.equals(".xml")) {
311                 extractor = new XMLTextExtractor();
312 
313                 contentType = "text/xml";
314             }
315 
316             if (extractor != null) {
317                 if (_log.isInfoEnabled()) {
318                     _log.info(
319                         "Using extractor " + extractor.getClass().getName() +
320                             " for extension " + fileExt);
321                 }
322 
323                 StringBuilder sb = new StringBuilder();
324 
325                 BufferedReader reader = new BufferedReader(
326                     extractor.extractText(is, contentType, encoding));
327 
328                 int i;
329 
330                 while ((i = reader.read()) != -1) {
331                     sb.append((char)i);
332                 }
333 
334                 reader.close();
335 
336                 text = sb.toString();
337             }
338             else {
339                 if (_log.isInfoEnabled()) {
340                     _log.info("No extractor found for extension " + fileExt);
341                 }
342             }
343         }
344         catch (Exception e) {
345             _log.error(e);
346         }
347 
348         if (_log.isDebugEnabled()) {
349             _log.debug("Extractor returned text:\n\n" + text);
350         }
351 
352         if (text == null) {
353             text = StringPool.BLANK;
354         }
355 
356         return text;
357     }
358 
359     public String getAbsolutePath(File file) {
360         return StringUtil.replace(
361             file.getAbsolutePath(), StringPool.BACK_SLASH, StringPool.SLASH);
362     }
363 
364     public byte[] getBytes(File file) throws IOException {
365         if ((file == null) || !file.exists()) {
366             return null;
367         }
368 
369         FileInputStream is = new FileInputStream(file);
370 
371         byte[] bytes = getBytes(is, (int)file.length());
372 
373         is.close();
374 
375         return bytes;
376     }
377 
378     public byte[] getBytes(InputStream is) throws IOException {
379         return getBytes(is, -1);
380     }
381 
382     public byte[] getBytes(InputStream is, int bufferSize) throws IOException {
383         ByteArrayMaker bam = null;
384 
385         if (bufferSize <= 0) {
386             bam = new ByteArrayMaker();
387         }
388         else {
389             bam = new ByteArrayMaker(bufferSize);
390         }
391 
392         boolean createBuffered = false;
393 
394         try {
395             if (!(is instanceof BufferedInputStream)) {
396                 is = new BufferedInputStream(is);
397 
398                 createBuffered = true;
399             }
400 
401             int c = is.read();
402 
403             while (c != -1) {
404                 bam.write(c);
405 
406                 c = is.read();
407             }
408         }
409         finally {
410             if (createBuffered) {
411                 is.close();
412             }
413         }
414 
415         bam.close();
416 
417         return bam.toByteArray();
418     }
419 
420     public String getExtension(String fileName) {
421         if (fileName == null) {
422             return null;
423         }
424 
425         int pos = fileName.lastIndexOf(StringPool.PERIOD);
426 
427         if (pos != -1) {
428             return fileName.substring(pos + 1, fileName.length()).toLowerCase();
429         }
430         else {
431             return null;
432         }
433     }
434 
435     public String getPath(String fullFileName) {
436         int pos = fullFileName.lastIndexOf(StringPool.SLASH);
437 
438         if (pos == -1) {
439             pos = fullFileName.lastIndexOf(StringPool.BACK_SLASH);
440         }
441 
442         String shortFileName = fullFileName.substring(0, pos);
443 
444         if (Validator.isNull(shortFileName)) {
445             return StringPool.SLASH;
446         }
447 
448         return shortFileName;
449     }
450 
451     public String getShortFileName(String fullFileName) {
452         int pos = fullFileName.lastIndexOf(StringPool.SLASH);
453 
454         if (pos == -1) {
455             pos = fullFileName.lastIndexOf(StringPool.BACK_SLASH);
456         }
457 
458         String shortFileName =
459             fullFileName.substring(pos + 1, fullFileName.length());
460 
461         return shortFileName;
462     }
463 
464     public boolean isAscii(File file) throws IOException {
465         boolean ascii = true;
466 
467         nsDetector detector = new nsDetector(nsPSMDetector.ALL);
468 
469         BufferedInputStream bis = new BufferedInputStream(
470             new FileInputStream(file));
471 
472         byte[] buffer = new byte[1024];
473 
474         int len = 0;
475 
476         while ((len = bis.read(buffer, 0, buffer.length)) != -1) {
477             if (ascii) {
478                 ascii = detector.isAscii(buffer, len);
479 
480                 if (!ascii) {
481                     break;
482                 }
483             }
484         }
485 
486         detector.DataEnd();
487 
488         return ascii;
489     }
490 
491     public String[] listDirs(String fileName) {
492         return listDirs(new File(fileName));
493     }
494 
495     public String[] listDirs(File file) {
496         List<String> dirs = new ArrayList<String>();
497 
498         File[] fileArray = file.listFiles();
499 
500         for (int i = 0; (fileArray != null) && (i < fileArray.length); i++) {
501             if (fileArray[i].isDirectory()) {
502                 dirs.add(fileArray[i].getName());
503             }
504         }
505 
506         return dirs.toArray(new String[dirs.size()]);
507     }
508 
509     public String[] listFiles(String fileName) {
510         if (Validator.isNull(fileName)) {
511             return new String[0];
512         }
513 
514         return listFiles(new File(fileName));
515     }
516 
517     public String[] listFiles(File file) {
518         List<String> files = new ArrayList<String>();
519 
520         File[] fileArray = file.listFiles();
521 
522         for (int i = 0; (fileArray != null) && (i < fileArray.length); i++) {
523             if (fileArray[i].isFile()) {
524                 files.add(fileArray[i].getName());
525             }
526         }
527 
528         return files.toArray(new String[files.size()]);
529     }
530 
531     public void mkdirs(String pathName) {
532         File file = new File(pathName);
533 
534         file.mkdirs();
535     }
536 
537     public boolean move(String sourceFileName, String destinationFileName) {
538         return move(new File(sourceFileName), new File(destinationFileName));
539     }
540 
541     public boolean move(File source, File destination) {
542         if (!source.exists()) {
543             return false;
544         }
545 
546         destination.delete();
547 
548         return source.renameTo(destination);
549     }
550 
551     public String read(String fileName) throws IOException {
552         return read(new File(fileName));
553     }
554 
555     public String read(File file) throws IOException {
556         return read(file, false);
557     }
558 
559     public String read(File file, boolean raw) throws IOException {
560         FileInputStream fis = new FileInputStream(file);
561 
562         byte[] bytes = new byte[fis.available()];
563 
564         fis.read(bytes);
565 
566         fis.close();
567 
568         String s = new String(bytes, StringPool.UTF8);
569 
570         if (raw) {
571             return s;
572         }
573         else {
574             return StringUtil.replace(
575                 s, StringPool.RETURN_NEW_LINE, StringPool.NEW_LINE);
576         }
577     }
578 
579     public String replaceSeparator(String fileName) {
580         return StringUtil.replace(
581             fileName, StringPool.BACK_SLASH, StringPool.SLASH);
582     }
583 
584     public File[] sortFiles(File[] files) {
585         if (files == null) {
586             return null;
587         }
588 
589         Arrays.sort(files, new FileComparator());
590 
591         List<File> directoryList = new ArrayList<File>();
592         List<File> fileList = new ArrayList<File>();
593 
594         for (int i = 0; i < files.length; i++) {
595             if (files[i].isDirectory()) {
596                 directoryList.add(files[i]);
597             }
598             else {
599                 fileList.add(files[i]);
600             }
601         }
602 
603         directoryList.addAll(fileList);
604 
605         return directoryList.toArray(new File[directoryList.size()]);
606     }
607 
608     public String stripExtension(String fileName) {
609         if (fileName == null) {
610             return null;
611         }
612 
613         int pos = fileName.lastIndexOf(StringPool.PERIOD);
614 
615         if (pos != -1) {
616             return fileName.substring(0, pos);
617         }
618         else {
619             return fileName;
620         }
621     }
622 
623     public List<String> toList(Reader reader) {
624         List<String> list = new ArrayList<String>();
625 
626         try {
627             BufferedReader br = new BufferedReader(reader);
628 
629             String line = null;
630 
631             while ((line = br.readLine()) != null) {
632                 list.add(line);
633             }
634 
635             br.close();
636         }
637         catch (IOException ioe) {
638         }
639 
640         return list;
641     }
642 
643     public List<String> toList(String fileName) {
644         try {
645             return toList(new FileReader(fileName));
646         }
647         catch (IOException ioe) {
648             return new ArrayList<String>();
649         }
650     }
651 
652     public Properties toProperties(FileInputStream fis) {
653         Properties props = new Properties();
654 
655         try {
656             props.load(fis);
657         }
658         catch (IOException ioe) {
659         }
660 
661         return props;
662     }
663 
664     public Properties toProperties(String fileName) {
665         try {
666             return toProperties(new FileInputStream(fileName));
667         }
668         catch (IOException ioe) {
669             return new Properties();
670         }
671     }
672 
673     public void write(String fileName, String s) throws IOException {
674         write(new File(fileName), s);
675     }
676 
677     public void write(String fileName, String s, boolean lazy)
678         throws IOException {
679 
680         write(new File(fileName), s, lazy);
681     }
682 
683     public void write(String fileName, String s, boolean lazy, boolean append)
684         throws IOException {
685 
686         write(new File(fileName), s, lazy, append);
687     }
688 
689     public void write(String pathName, String fileName, String s)
690         throws IOException {
691 
692         write(new File(pathName, fileName), s);
693     }
694 
695     public void write(String pathName, String fileName, String s, boolean lazy)
696         throws IOException {
697 
698         write(new File(pathName, fileName), s, lazy);
699     }
700 
701     public void write(
702             String pathName, String fileName, String s, boolean lazy,
703             boolean append)
704         throws IOException {
705 
706         write(new File(pathName, fileName), s, lazy, append);
707     }
708 
709     public void write(File file, String s) throws IOException {
710         write(file, s, false);
711     }
712 
713     public void write(File file, String s, boolean lazy)
714         throws IOException {
715 
716         write(file, s, lazy, false);
717     }
718 
719     public void write(File file, String s, boolean lazy, boolean append)
720         throws IOException {
721 
722         if (file.getParent() != null) {
723             mkdirs(file.getParent());
724         }
725 
726         if (lazy && file.exists()) {
727             String content = read(file);
728 
729             if (content.equals(s)) {
730                 return;
731             }
732         }
733 
734         BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
735             new FileOutputStream(file, append), StringPool.UTF8));
736 
737         bw.write(s);
738 
739         bw.close();
740     }
741 
742     public void write(String fileName, byte[] bytes) throws IOException {
743         write(new File(fileName), bytes);
744     }
745 
746     public void write(File file, byte[] bytes) throws IOException {
747         if (file.getParent() != null) {
748             mkdirs(file.getParent());
749         }
750 
751         FileOutputStream fos = new FileOutputStream(file);
752 
753         fos.write(bytes);
754 
755         fos.close();
756     }
757 
758     public void write(String fileName, InputStream is) throws IOException {
759         write(fileName, getBytes(is));
760     }
761 
762     public void write(File file, InputStream is) throws IOException {
763         write(file, getBytes(is));
764     }
765 
766     private static Log _log = LogFactoryUtil.getLog(FileImpl.class);
767 
768     private static FileImpl _instance = new FileImpl();
769 
770 }