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