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