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