001
014
015 package com.liferay.portal.util;
016
017 import com.liferay.portal.kernel.io.unsync.UnsyncBufferedReader;
018 import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayInputStream;
019 import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayOutputStream;
020 import com.liferay.portal.kernel.log.Log;
021 import com.liferay.portal.kernel.log.LogFactoryUtil;
022 import com.liferay.portal.kernel.nio.charset.CharsetEncoderUtil;
023 import com.liferay.portal.kernel.process.ClassPathUtil;
024 import com.liferay.portal.kernel.process.ProcessCallable;
025 import com.liferay.portal.kernel.process.ProcessException;
026 import com.liferay.portal.kernel.process.ProcessExecutor;
027 import com.liferay.portal.kernel.security.pacl.DoPrivileged;
028 import com.liferay.portal.kernel.util.ArrayUtil;
029 import com.liferay.portal.kernel.util.CharPool;
030 import com.liferay.portal.kernel.util.FileComparator;
031 import com.liferay.portal.kernel.util.StreamUtil;
032 import com.liferay.portal.kernel.util.StringBundler;
033 import com.liferay.portal.kernel.util.StringPool;
034 import com.liferay.portal.kernel.util.StringUtil;
035 import com.liferay.portal.kernel.util.SystemProperties;
036 import com.liferay.portal.kernel.util.Time;
037 import com.liferay.portal.kernel.util.Validator;
038 import com.liferay.util.PwdGenerator;
039 import com.liferay.util.ant.ExpandTask;
040
041 import java.io.File;
042 import java.io.FileInputStream;
043 import java.io.FileOutputStream;
044 import java.io.FileReader;
045 import java.io.IOException;
046 import java.io.InputStream;
047 import java.io.OutputStreamWriter;
048 import java.io.RandomAccessFile;
049 import java.io.Reader;
050 import java.io.Writer;
051
052 import java.nio.ByteBuffer;
053 import java.nio.channels.FileChannel;
054
055 import java.util.ArrayList;
056 import java.util.Arrays;
057 import java.util.List;
058 import java.util.Properties;
059 import java.util.concurrent.Future;
060
061 import org.apache.commons.io.FileUtils;
062 import org.apache.commons.lang.exception.ExceptionUtils;
063 import org.apache.pdfbox.exceptions.CryptographyException;
064 import org.apache.poi.EncryptedDocumentException;
065 import org.apache.tika.Tika;
066 import org.apache.tools.ant.DirectoryScanner;
067
068 import org.mozilla.intl.chardet.nsDetector;
069 import org.mozilla.intl.chardet.nsPSMDetector;
070
071
075 @DoPrivileged
076 public class FileImpl implements com.liferay.portal.kernel.util.File {
077
078 public static FileImpl getInstance() {
079 return _instance;
080 }
081
082 public void copyDirectory(File source, File destination)
083 throws IOException {
084
085 if (source.exists() && source.isDirectory()) {
086 if (!destination.exists()) {
087 destination.mkdirs();
088 }
089
090 File[] fileArray = source.listFiles();
091
092 for (int i = 0; i < fileArray.length; i++) {
093 if (fileArray[i].isDirectory()) {
094 copyDirectory(
095 fileArray[i],
096 new File(
097 destination.getPath() + File.separator +
098 fileArray[i].getName()));
099 }
100 else {
101 copyFile(
102 fileArray[i],
103 new File(
104 destination.getPath() + File.separator +
105 fileArray[i].getName()));
106 }
107 }
108 }
109 }
110
111 public void copyDirectory(String sourceDirName, String destinationDirName)
112 throws IOException {
113
114 copyDirectory(new File(sourceDirName), new File(destinationDirName));
115 }
116
117 public void copyFile(File source, File destination) throws IOException {
118 copyFile(source, destination, false);
119 }
120
121 public void copyFile(File source, File destination, boolean lazy)
122 throws IOException {
123
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 mkdirsParentFile(destination);
152
153 StreamUtil.transfer(
154 new FileInputStream(source), new FileOutputStream(destination));
155 }
156 }
157
158 public void copyFile(String source, String destination) throws IOException {
159 copyFile(source, destination, false);
160 }
161
162 public void copyFile(String source, String destination, boolean lazy)
163 throws IOException {
164
165 copyFile(new File(source), new File(destination), lazy);
166 }
167
168 public File createTempFile() {
169 return createTempFile(StringPool.BLANK);
170 }
171
172 public File createTempFile(byte[] bytes) throws IOException {
173 File file = createTempFile(StringPool.BLANK);
174
175 write(file, bytes);
176
177 return file;
178 }
179
180 public File createTempFile(InputStream is) throws IOException {
181 File file = createTempFile(StringPool.BLANK);
182
183 write(file, is);
184
185 return file;
186 }
187
188 public File createTempFile(String extension) {
189 return new File(createTempFileName(extension));
190 }
191
192 public String createTempFileName() {
193 return createTempFileName(null);
194 }
195
196 public String createTempFileName(String extension) {
197 StringBundler sb = new StringBundler();
198
199 sb.append(SystemProperties.get(SystemProperties.TMP_DIR));
200 sb.append(StringPool.SLASH);
201 sb.append(Time.getTimestamp());
202 sb.append(PwdGenerator.getPassword(PwdGenerator.KEY2, 8));
203
204 if (Validator.isFileExtension(extension)) {
205 sb.append(StringPool.PERIOD);
206 sb.append(extension);
207 }
208
209 return sb.toString();
210 }
211
212 public File createTempFolder() {
213 File file = new File(createTempFileName());
214
215 file.mkdirs();
216
217 return file;
218 }
219
220 public String decodeSafeFileName(String fileName) {
221 return StringUtil.replace(
222 fileName, _SAFE_FILE_NAME_2, _SAFE_FILE_NAME_1);
223 }
224
225 public boolean delete(File file) {
226 if (file != null) {
227 boolean exists = true;
228
229 try {
230 exists = file.exists();
231 }
232 catch (SecurityException se) {
233
234
235
236
237 }
238
239 if (exists) {
240 return file.delete();
241 }
242 }
243
244 return false;
245 }
246
247 public boolean delete(String file) {
248 return delete(new File(file));
249 }
250
251 public void deltree(File directory) {
252 if (directory.exists() && directory.isDirectory()) {
253 File[] fileArray = directory.listFiles();
254
255 for (int i = 0; i < fileArray.length; i++) {
256 if (fileArray[i].isDirectory()) {
257 deltree(fileArray[i]);
258 }
259 else {
260 fileArray[i].delete();
261 }
262 }
263
264 directory.delete();
265 }
266 }
267
268 public void deltree(String directory) {
269 deltree(new File(directory));
270 }
271
272 public String encodeSafeFileName(String fileName) {
273 if (fileName == null) {
274 return StringPool.BLANK;
275 }
276
277 return StringUtil.replace(
278 fileName, _SAFE_FILE_NAME_1, _SAFE_FILE_NAME_2);
279 }
280
281 public boolean exists(File file) {
282 return file.exists();
283 }
284
285 public boolean exists(String fileName) {
286 return exists(new File(fileName));
287 }
288
289 public String extractText(InputStream is, String fileName) {
290 String text = null;
291
292 ClassLoader portalClassLoader = ClassLoaderUtil.getPortalClassLoader();
293
294 ClassLoader contextClassLoader =
295 ClassLoaderUtil.getContextClassLoader();
296
297 try {
298 if (contextClassLoader != portalClassLoader) {
299 ClassLoaderUtil.setContextClassLoader(portalClassLoader);
300 }
301
302 Tika tika = new Tika();
303
304 tika.setMaxStringLength(-1);
305
306 boolean forkProcess = false;
307
308 if (PropsValues.TEXT_EXTRACTION_FORK_PROCESS_ENABLED) {
309 String mimeType = tika.detect(is);
310
311 if (ArrayUtil.contains(
312 PropsValues.TEXT_EXTRACTION_FORK_PROCESS_MIME_TYPES,
313 mimeType)) {
314
315 forkProcess = true;
316 }
317 }
318
319 if (forkProcess) {
320 Future<String> future = ProcessExecutor.execute(
321 ClassPathUtil.getPortalClassPath(),
322 new ExtractTextProcessCallable(getBytes(is)));
323
324 text = future.get();
325 }
326 else {
327 text = tika.parseToString(is);
328 }
329 }
330 catch (Exception e) {
331 Throwable throwable = ExceptionUtils.getRootCause(e);
332
333 if ((throwable instanceof CryptographyException) ||
334 (throwable instanceof EncryptedDocumentException)) {
335
336 if (_log.isWarnEnabled()) {
337 _log.warn("Unable to extract text from an encrypted file");
338 }
339 }
340 else {
341 _log.error(e, e);
342 }
343 }
344 finally {
345 if (contextClassLoader != portalClassLoader) {
346 ClassLoaderUtil.setContextClassLoader(contextClassLoader);
347 }
348 }
349
350 if (_log.isInfoEnabled()) {
351 if (text == null) {
352 _log.info("Text extraction failed for " + fileName);
353 }
354 else {
355 _log.info("Text was extracted for " + fileName);
356 }
357 }
358
359 if (_log.isDebugEnabled()) {
360 _log.debug("Extractor returned text:\n\n" + text);
361 }
362
363 if (text == null) {
364 text = StringPool.BLANK;
365 }
366
367 return text;
368 }
369
370 public String[] find(String directory, String includes, String excludes) {
371 if (directory.length() > 0) {
372 directory = replaceSeparator(directory);
373
374 if (directory.charAt(directory.length() - 1) == CharPool.SLASH) {
375 directory = directory.substring(0, directory.length() - 1);
376 }
377 }
378
379 if (!exists(directory)) {
380 if (_log.isWarnEnabled()) {
381 _log.warn("Directory " + directory + " does not exist");
382 }
383
384 return new String[0];
385 }
386
387 DirectoryScanner directoryScanner = new DirectoryScanner();
388
389 directoryScanner.setBasedir(directory);
390 directoryScanner.setExcludes(StringUtil.split(excludes));
391 directoryScanner.setIncludes(StringUtil.split(includes));
392
393 directoryScanner.scan();
394
395 String[] includedFiles = directoryScanner.getIncludedFiles();
396
397 for (int i = 0; i < includedFiles.length; i++) {
398 includedFiles[i] = directory.concat(
399 StringPool.SLASH).concat(replaceSeparator(includedFiles[i]));
400 }
401
402 return includedFiles;
403 }
404
405 public String getAbsolutePath(File file) {
406 return StringUtil.replace(
407 file.getAbsolutePath(), CharPool.BACK_SLASH, CharPool.SLASH);
408 }
409
410 public byte[] getBytes(File file) throws IOException {
411 if ((file == null) || !file.exists()) {
412 return null;
413 }
414
415 RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r");
416
417 byte[] bytes = new byte[(int)randomAccessFile.length()];
418
419 randomAccessFile.readFully(bytes);
420
421 randomAccessFile.close();
422
423 return bytes;
424 }
425
426 public byte[] getBytes(InputStream is) throws IOException {
427 return getBytes(is, -1);
428 }
429
430 public byte[] getBytes(InputStream inputStream, int bufferSize)
431 throws IOException {
432
433 return getBytes(inputStream, bufferSize, true);
434 }
435
436 public byte[] getBytes(
437 InputStream inputStream, int bufferSize, boolean cleanUpStream)
438 throws IOException {
439
440 if (inputStream == null) {
441 return null;
442 }
443
444 UnsyncByteArrayOutputStream unsyncByteArrayOutputStream =
445 new UnsyncByteArrayOutputStream();
446
447 StreamUtil.transfer(
448 inputStream, unsyncByteArrayOutputStream, bufferSize,
449 cleanUpStream);
450
451 return unsyncByteArrayOutputStream.toByteArray();
452 }
453
454 public String getExtension(String fileName) {
455 if (fileName == null) {
456 return null;
457 }
458
459 int pos = fileName.lastIndexOf(CharPool.PERIOD);
460
461 if (pos > 0) {
462 return fileName.substring(pos + 1, fileName.length()).toLowerCase();
463 }
464 else {
465 return StringPool.BLANK;
466 }
467 }
468
469 public String getPath(String fullFileName) {
470 int x = fullFileName.lastIndexOf(CharPool.SLASH);
471 int y = fullFileName.lastIndexOf(CharPool.BACK_SLASH);
472
473 if ((x == -1) && (y == -1)) {
474 return StringPool.SLASH;
475 }
476
477 String shortFileName = fullFileName.substring(0, Math.max(x, y));
478
479 return shortFileName;
480 }
481
482 public String getShortFileName(String fullFileName) {
483 int x = fullFileName.lastIndexOf(CharPool.SLASH);
484 int y = fullFileName.lastIndexOf(CharPool.BACK_SLASH);
485
486 String shortFileName = fullFileName.substring(Math.max(x, y) + 1);
487
488 return shortFileName;
489 }
490
491 public boolean isAscii(File file) throws IOException {
492 boolean ascii = true;
493
494 nsDetector detector = new nsDetector(nsPSMDetector.ALL);
495
496 InputStream inputStream = new FileInputStream(file);
497
498 byte[] buffer = new byte[1024];
499
500 int len = 0;
501
502 while ((len = inputStream.read(buffer, 0, buffer.length)) != -1) {
503 if (ascii) {
504 ascii = detector.isAscii(buffer, len);
505
506 if (!ascii) {
507 break;
508 }
509 }
510 }
511
512 detector.DataEnd();
513
514 inputStream.close();
515
516 return ascii;
517 }
518
519 public boolean isSameContent(File file, byte[] bytes, int length) {
520 FileChannel fileChannel = null;
521
522 try {
523 FileInputStream fileInputStream = new FileInputStream(file);
524
525 fileChannel = fileInputStream.getChannel();
526
527 if (fileChannel.size() != length) {
528 return false;
529 }
530
531 byte[] buffer = new byte[1024];
532
533 ByteBuffer byteBuffer = ByteBuffer.wrap(buffer);
534
535 int bufferIndex = 0;
536 int bufferLength = -1;
537
538 while (((bufferLength = fileChannel.read(byteBuffer)) > 0) &&
539 (bufferIndex < length)) {
540
541 for (int i = 0; i < bufferLength; i++) {
542 if (buffer[i] != bytes[bufferIndex++]) {
543 return false;
544 }
545 }
546
547 byteBuffer.clear();
548 }
549
550 if ((bufferIndex != length) || (bufferLength != -1)) {
551 return false;
552 }
553 else {
554 return true;
555 }
556 }
557 catch (Exception e) {
558 return false;
559 }
560 finally {
561 if (fileChannel != null) {
562 try {
563 fileChannel.close();
564 }
565 catch (IOException ioe) {
566 }
567 }
568 }
569 }
570
571 public boolean isSameContent(File file, String s) {
572 ByteBuffer byteBuffer = CharsetEncoderUtil.encode(StringPool.UTF8, s);
573
574 return isSameContent(file, byteBuffer.array(), byteBuffer.limit());
575 }
576
577 public String[] listDirs(File file) {
578 List<String> dirs = new ArrayList<String>();
579
580 File[] fileArray = file.listFiles();
581
582 for (int i = 0; (fileArray != null) && (i < fileArray.length); i++) {
583 if (fileArray[i].isDirectory()) {
584 dirs.add(fileArray[i].getName());
585 }
586 }
587
588 return dirs.toArray(new String[dirs.size()]);
589 }
590
591 public String[] listDirs(String fileName) {
592 return listDirs(new File(fileName));
593 }
594
595 public String[] listFiles(File file) {
596 List<String> files = new ArrayList<String>();
597
598 File[] fileArray = file.listFiles();
599
600 for (int i = 0; (fileArray != null) && (i < fileArray.length); i++) {
601 if (fileArray[i].isFile()) {
602 files.add(fileArray[i].getName());
603 }
604 }
605
606 return files.toArray(new String[files.size()]);
607 }
608
609 public String[] listFiles(String fileName) {
610 if (Validator.isNull(fileName)) {
611 return new String[0];
612 }
613
614 return listFiles(new File(fileName));
615 }
616
617 public void mkdirs(String pathName) {
618 File file = new File(pathName);
619
620 file.mkdirs();
621 }
622
623 public boolean move(File source, File destination) {
624 if (!source.exists()) {
625 return false;
626 }
627
628 destination.delete();
629
630 try {
631 if (source.isDirectory()) {
632 FileUtils.moveDirectory(source, destination);
633 }
634 else {
635 FileUtils.moveFile(source, destination);
636 }
637 }
638 catch (IOException ioe) {
639 return false;
640 }
641
642 return true;
643 }
644
645 public boolean move(String sourceFileName, String destinationFileName) {
646 return move(new File(sourceFileName), new File(destinationFileName));
647 }
648
649 public String read(File file) throws IOException {
650 return read(file, false);
651 }
652
653 public String read(File file, boolean raw) throws IOException {
654 byte[] bytes = getBytes(file);
655
656 if (bytes == null) {
657 return null;
658 }
659
660 String s = new String(bytes, StringPool.UTF8);
661
662 if (raw) {
663 return s;
664 }
665 else {
666 return StringUtil.replace(
667 s, StringPool.RETURN_NEW_LINE, StringPool.NEW_LINE);
668 }
669 }
670
671 public String read(String fileName) throws IOException {
672 return read(new File(fileName));
673 }
674
675 public String replaceSeparator(String fileName) {
676 return StringUtil.replace(
677 fileName, CharPool.BACK_SLASH, CharPool.SLASH);
678 }
679
680 public File[] sortFiles(File[] files) {
681 if (files == null) {
682 return null;
683 }
684
685 Arrays.sort(files, new FileComparator());
686
687 List<File> directoryList = new ArrayList<File>();
688 List<File> fileList = new ArrayList<File>();
689
690 for (int i = 0; i < files.length; i++) {
691 if (files[i].isDirectory()) {
692 directoryList.add(files[i]);
693 }
694 else {
695 fileList.add(files[i]);
696 }
697 }
698
699 directoryList.addAll(fileList);
700
701 return directoryList.toArray(new File[directoryList.size()]);
702 }
703
704 public String stripExtension(String fileName) {
705 if (fileName == null) {
706 return null;
707 }
708
709 String ext = getExtension(fileName);
710
711 if (ext.length() > 0) {
712 return fileName.substring(0, fileName.length() - ext.length() - 1);
713 }
714 else {
715 return fileName;
716 }
717 }
718
719 public List<String> toList(Reader reader) {
720 List<String> list = new ArrayList<String>();
721
722 try {
723 UnsyncBufferedReader unsyncBufferedReader =
724 new UnsyncBufferedReader(reader);
725
726 String line = null;
727
728 while ((line = unsyncBufferedReader.readLine()) != null) {
729 list.add(line);
730 }
731
732 unsyncBufferedReader.close();
733 }
734 catch (IOException ioe) {
735 }
736
737 return list;
738 }
739
740 public List<String> toList(String fileName) {
741 try {
742 return toList(new FileReader(fileName));
743 }
744 catch (IOException ioe) {
745 return new ArrayList<String>();
746 }
747 }
748
749 public Properties toProperties(FileInputStream fis) {
750 Properties properties = new Properties();
751
752 try {
753 properties.load(fis);
754 }
755 catch (IOException ioe) {
756 }
757
758 return properties;
759 }
760
761 public Properties toProperties(String fileName) {
762 try {
763 return toProperties(new FileInputStream(fileName));
764 }
765 catch (IOException ioe) {
766 return new Properties();
767 }
768 }
769
770 public void touch(File file) throws IOException {
771 FileUtils.touch(file);
772 }
773
774 public void touch(String fileName) throws IOException {
775 touch(new File(fileName));
776 }
777
778 public void unzip(File source, File destination) {
779 ExpandTask.expand(source, destination);
780 }
781
782 public void write(File file, byte[] bytes) throws IOException {
783 write(file, bytes, 0, bytes.length);
784 }
785
786 public void write(File file, byte[] bytes, int offset, int length)
787 throws IOException {
788
789 mkdirsParentFile(file);
790
791 FileOutputStream fileOutputStream = new FileOutputStream(file);
792
793 fileOutputStream.write(bytes, offset, length);
794
795 fileOutputStream.close();
796 }
797
798 public void write(File file, InputStream is) throws IOException {
799 mkdirsParentFile(file);
800
801 StreamUtil.transfer(is, new FileOutputStream(file));
802 }
803
804 public void write(File file, String s) throws IOException {
805 write(file, s, false);
806 }
807
808 public void write(File file, String s, boolean lazy) throws IOException {
809 write(file, s, lazy, false);
810 }
811
812 public void write(File file, String s, boolean lazy, boolean append)
813 throws IOException {
814
815 if (s == null) {
816 return;
817 }
818
819 mkdirsParentFile(file);
820
821 if (lazy && file.exists()) {
822 String content = read(file);
823
824 if (content.equals(s)) {
825 return;
826 }
827 }
828
829 Writer writer = new OutputStreamWriter(
830 new FileOutputStream(file, append), StringPool.UTF8);
831
832 writer.write(s);
833
834 writer.close();
835 }
836
837 public void write(String fileName, byte[] bytes) throws IOException {
838 write(new File(fileName), bytes);
839 }
840
841 public void write(String fileName, InputStream is) throws IOException {
842 write(new File(fileName), is);
843 }
844
845 public void write(String fileName, String s) throws IOException {
846 write(new File(fileName), s);
847 }
848
849 public void write(String fileName, String s, boolean lazy)
850 throws IOException {
851
852 write(new File(fileName), s, lazy);
853 }
854
855 public void write(String fileName, String s, boolean lazy, boolean append)
856 throws IOException {
857
858 write(new File(fileName), s, lazy, append);
859 }
860
861 public void write(String pathName, String fileName, String s)
862 throws IOException {
863
864 write(new File(pathName, fileName), s);
865 }
866
867 public void write(String pathName, String fileName, String s, boolean lazy)
868 throws IOException {
869
870 write(new File(pathName, fileName), s, lazy);
871 }
872
873 public void write(
874 String pathName, String fileName, String s, boolean lazy,
875 boolean append)
876 throws IOException {
877
878 write(new File(pathName, fileName), s, lazy, append);
879 }
880
881 protected void mkdirsParentFile(File file) {
882 File parentFile = file.getParentFile();
883
884 if (parentFile == null) {
885 return;
886 }
887
888 try {
889 if (!parentFile.exists()) {
890 parentFile.mkdirs();
891 }
892 }
893 catch (SecurityException se) {
894
895
896
897
898 }
899 }
900
901 private static final String[] _SAFE_FILE_NAME_1 = {
902 StringPool.AMPERSAND, StringPool.CLOSE_PARENTHESIS,
903 StringPool.OPEN_PARENTHESIS, StringPool.SEMICOLON
904 };
905
906 private static final String[] _SAFE_FILE_NAME_2 = {
907 "_AMP_", "_CP_", "_OP_", "_SEM_"
908 };
909
910 private static Log _log = LogFactoryUtil.getLog(FileImpl.class);
911
912 private static FileImpl _instance = new FileImpl();
913
914 private static class ExtractTextProcessCallable
915 implements ProcessCallable<String> {
916
917 public ExtractTextProcessCallable(byte[] data) {
918 _data = data;
919 }
920
921 public String call() throws ProcessException {
922 Tika tika = new Tika();
923
924 try {
925 return tika.parseToString(
926 new UnsyncByteArrayInputStream(_data));
927 }
928 catch (Exception e) {
929 throw new ProcessException(e);
930 }
931 }
932
933 private static final long serialVersionUID = 1L;
934
935 private byte[] _data;
936
937 }
938
939 }