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