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