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