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