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