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