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