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