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