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