001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portlet.documentlibrary.store;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayInputStream;
020    import com.liferay.portal.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.util.FileUtil;
023    import com.liferay.portal.kernel.util.StringPool;
024    import com.liferay.portlet.documentlibrary.DuplicateFileException;
025    import com.liferay.portlet.documentlibrary.NoSuchFileException;
026    
027    import java.io.File;
028    import java.io.FileInputStream;
029    import java.io.FileNotFoundException;
030    import java.io.IOException;
031    import java.io.InputStream;
032    
033    /**
034     * The abstract base class for all file store implementations. Most, if not all
035     * implementations should extend this class.
036     *
037     * @author Brian Wing Shun Chan
038     * @author Alexander Chow
039     * @author Edward Han
040     */
041    public abstract class BaseStore implements Store {
042    
043            /**
044             * Adds a directory.
045             *
046             * @param  companyId the primary key of the company
047             * @param  repositoryId the primary key of the data repository (optionally
048             *         {@link com.liferay.portal.model.CompanyConstants#SYSTEM})
049             * @param  dirName the directory's name
050             * @throws PortalException if the directory's information was invalid
051             * @throws SystemException if a system exception occurred
052             */
053            @Override
054            public abstract void addDirectory(
055                            long companyId, long repositoryId, String dirName)
056                    throws PortalException, SystemException;
057    
058            /**
059             * Adds a file based on a byte array.
060             *
061             * @param  companyId the primary key of the company
062             * @param  repositoryId the primary key of the data repository (optionally
063             *         {@link com.liferay.portal.model.CompanyConstants#SYSTEM})
064             * @param  fileName the file name
065             * @param  bytes the files's data
066             * @throws PortalException if the file's information was invalid
067             * @throws SystemException if a system exception occurred
068             */
069            @Override
070            public void addFile(
071                            long companyId, long repositoryId, String fileName, byte[] bytes)
072                    throws PortalException, SystemException {
073    
074                    File file = null;
075    
076                    try {
077                            file = FileUtil.createTempFile(bytes);
078    
079                            addFile(companyId, repositoryId, fileName, file);
080                    }
081                    catch (IOException ioe) {
082                            throw new SystemException("Unable to write temporary file", ioe);
083                    }
084                    finally {
085                            FileUtil.delete(file);
086                    }
087            }
088    
089            /**
090             * Adds a file based on a {@link File} object.
091             *
092             * @param  companyId the primary key of the company
093             * @param  repositoryId the primary key of the data repository (optionally
094             *         {@link com.liferay.portal.model.CompanyConstants#SYSTEM})
095             * @param  fileName the file name
096             * @param  file Name the file name
097             * @throws PortalException if the file's information was invalid
098             * @throws SystemException if a system exception occurred
099             */
100            @Override
101            public void addFile(
102                            long companyId, long repositoryId, String fileName, File file)
103                    throws PortalException, SystemException {
104    
105                    InputStream is = null;
106    
107                    try {
108                            is = new FileInputStream(file);
109    
110                            addFile(companyId, repositoryId, fileName, is);
111                    }
112                    catch (FileNotFoundException fnfe) {
113                            throw new NoSuchFileException(fileName);
114                    }
115                    finally {
116                            try {
117                                    if (is != null) {
118                                            is.close();
119                                    }
120                            }
121                            catch (IOException ioe) {
122                                    _log.error(ioe);
123                            }
124                    }
125            }
126    
127            /**
128             * Adds a file based on an {@link InputStream} object.
129             *
130             * @param  companyId the primary key of the company
131             * @param  repositoryId the primary key of the data repository (optionally
132             *         {@link com.liferay.portal.model.CompanyConstants#SYSTEM})
133             * @param  fileName the file name
134             * @param  is the files's data
135             * @throws PortalException if the file's information was invalid
136             * @throws SystemException if a system exception occurred
137             */
138            @Override
139            public abstract void addFile(
140                            long companyId, long repositoryId, String fileName, InputStream is)
141                    throws PortalException, SystemException;
142    
143            /**
144             * Ensures company's root directory exists. Only implemented by {@link
145             * JCRStore#checkRoot(long)}.
146             *
147             * @param  companyId the primary key of the company
148             * @throws SystemException if a system exception occurred
149             */
150            @Override
151            public abstract void checkRoot(long companyId) throws SystemException;
152    
153            /**
154             * Creates a new copy of the file version.
155             *
156             * <p>
157             * This method should be overrided if a more optimized approach can be used
158             * (e.g., {@link FileSystemStore#copyFileVersion(long, long, String, String,
159             * String)}).
160             * </p>
161             *
162             * @param  companyId the primary key of the company
163             * @param  repositoryId the primary key of the data repository (optionally
164             *         {@link com.liferay.portal.model.CompanyConstants#SYSTEM})
165             * @param  fileName the original's file name
166             * @param  fromVersionLabel the original file's version label
167             * @param  toVersionLabel the new version label
168             * @throws PortalException if the file's information was invalid
169             * @throws SystemException if a system exception occurred
170             */
171            @Override
172            public void copyFileVersion(
173                            long companyId, long repositoryId, String fileName,
174                            String fromVersionLabel, String toVersionLabel)
175                    throws PortalException, SystemException {
176    
177                    if (fromVersionLabel.equals(toVersionLabel)) {
178                            throw new DuplicateFileException(
179                                    String.format(
180                                            "{companyId=%s, fileName=%s, repositoryId=%s, version=%s}",
181                                            companyId, fileName, repositoryId, toVersionLabel));
182                    }
183    
184                    InputStream is = getFileAsStream(
185                            companyId, repositoryId, fileName, fromVersionLabel);
186    
187                    if (is == null) {
188                            is = new UnsyncByteArrayInputStream(new byte[0]);
189                    }
190    
191                    updateFile(companyId, repositoryId, fileName, toVersionLabel, is);
192            }
193    
194            /**
195             * Deletes a directory.
196             *
197             * @param  companyId the primary key of the company
198             * @param  repositoryId the primary key of the data repository (optionally
199             *         {@link com.liferay.portal.model.CompanyConstants#SYSTEM})
200             * @param  dirName the directory's name
201             * @throws PortalException if the directory's information was invalid
202             * @throws SystemException if a system exception occurred
203             */
204            @Override
205            public abstract void deleteDirectory(
206                            long companyId, long repositoryId, String dirName)
207                    throws PortalException, SystemException;
208    
209            /**
210             * Deletes a file. If a file has multiple versions, all versions will be
211             * deleted.
212             *
213             * @param  companyId the primary key of the company
214             * @param  repositoryId the primary key of the data repository (optionally
215             *         {@link com.liferay.portal.model.CompanyConstants#SYSTEM})
216             * @param  fileName the file's name
217             * @throws PortalException if the file's information was invalid
218             * @throws SystemException if a system exception occurred
219             */
220            @Override
221            public abstract void deleteFile(
222                            long companyId, long repositoryId, String fileName)
223                    throws PortalException, SystemException;
224    
225            /**
226             * Deletes a file at a particular version.
227             *
228             * @param  companyId the primary key of the company
229             * @param  repositoryId the primary key of the data repository (optionally
230             *         {@link com.liferay.portal.model.CompanyConstants#SYSTEM})
231             * @param  fileName the file's name
232             * @param  versionLabel the file's version label
233             * @throws PortalException if the file's information was invalid
234             * @throws SystemException if a system exception occurred
235             */
236            @Override
237            public abstract void deleteFile(
238                            long companyId, long repositoryId, String fileName,
239                            String versionLabel)
240                    throws PortalException, SystemException;
241    
242            /**
243             * Returns the file as a {@link File} object.
244             *
245             * <p>
246             * This method is useful when optimizing low-level file operations like
247             * copy. The client must not delete or change the returned {@link File}
248             * object in any way. This method is only supported in certain stores. If
249             * not supported, this method will throw an {@link
250             * UnsupportedOperationException}.
251             * </p>
252             *
253             * @param  companyId the primary key of the company
254             * @param  repositoryId the primary key of the data repository (optionally
255             *         {@link com.liferay.portal.model.CompanyConstants#SYSTEM})
256             * @param  fileName the file's name
257             * @return Returns the {@link File} object with the file's name
258             * @throws PortalException if the file's information was invalid
259             * @throws SystemException if a system exception occurred
260             */
261            @Override
262            public File getFile(long companyId, long repositoryId, String fileName)
263                    throws PortalException, SystemException {
264    
265                    return getFile(companyId, repositoryId, fileName, StringPool.BLANK);
266            }
267    
268            /**
269             * Returns the file as a {@link File} object.
270             *
271             * <p>
272             * This method is useful when optimizing low-level file operations like
273             * copy. The client must not delete or change the returned {@link File}
274             * object in any way. This method is only supported in certain stores. If
275             * not supported, this method will throw an {@link
276             * UnsupportedOperationException}.
277             * </p>
278             *
279             * <p>
280             * This method should be overrided if a more optimized approach can be used
281             * (e.g., {@link FileSystemStore#getFile(long, long, String, String)}).
282             * </p>
283             *
284             * @param  companyId the primary key of the company
285             * @param  repositoryId the primary key of the data repository (optionally
286             *         {@link com.liferay.portal.model.CompanyConstants#SYSTEM})
287             * @param  fileName the file's name
288             * @param  versionLabel the file's version label
289             * @return Returns the {@link File} object with the file's name
290             * @throws PortalException if the file's information was invalid
291             * @throws SystemException if a system exception occurred
292             */
293            @Override
294            public File getFile(
295                            long companyId, long repositoryId, String fileName,
296                            String versionLabel)
297                    throws PortalException, SystemException {
298    
299                    throw new UnsupportedOperationException();
300            }
301    
302            /**
303             * Returns the file as a byte array.
304             *
305             * @param  companyId the primary key of the company
306             * @param  repositoryId the primary key of the data repository (optionally
307             *         {@link com.liferay.portal.model.CompanyConstants#SYSTEM})
308             * @param  fileName the file's name
309             * @return Returns the byte array with the file's name
310             * @throws PortalException if the file's information was invalid
311             * @throws SystemException if a system exception occurred
312             */
313            @Override
314            public byte[] getFileAsBytes(
315                            long companyId, long repositoryId, String fileName)
316                    throws PortalException, SystemException {
317    
318                    byte[] bytes = null;
319    
320                    try {
321                            InputStream is = getFileAsStream(companyId, repositoryId, fileName);
322    
323                            bytes = FileUtil.getBytes(is);
324                    }
325                    catch (IOException ioe) {
326                            throw new SystemException(ioe);
327                    }
328    
329                    return bytes;
330            }
331    
332            /**
333             * Returns the file as a byte array.
334             *
335             * @param  companyId the primary key of the company
336             * @param  repositoryId the primary key of the data repository (optionally
337             *         {@link com.liferay.portal.model.CompanyConstants#SYSTEM})
338             * @param  fileName the file's name
339             * @param  versionLabel the file's version label
340             * @return Returns the byte array with the file's name
341             * @throws PortalException if the file's information was invalid
342             * @throws SystemException if a system exception occurred
343             */
344            @Override
345            public byte[] getFileAsBytes(
346                            long companyId, long repositoryId, String fileName,
347                            String versionLabel)
348                    throws PortalException, SystemException {
349    
350                    byte[] bytes = null;
351    
352                    try {
353                            InputStream is = getFileAsStream(
354                                    companyId, repositoryId, fileName, versionLabel);
355    
356                            bytes = FileUtil.getBytes(is);
357                    }
358                    catch (IOException ioe) {
359                            throw new SystemException(ioe);
360                    }
361    
362                    return bytes;
363            }
364    
365            /**
366             * Returns the file as an {@link InputStream} object.
367             *
368             * @param  companyId the primary key of the company
369             * @param  repositoryId the primary key of the data repository (optionally
370             *         {@link com.liferay.portal.model.CompanyConstants#SYSTEM})
371             * @param  fileName the file's name
372             * @return Returns the {@link InputStream} object with the file's name
373             * @throws PortalException if the file's information was invalid
374             * @throws SystemException if a system exception occurred
375             */
376            @Override
377            public InputStream getFileAsStream(
378                            long companyId, long repositoryId, String fileName)
379                    throws PortalException, SystemException {
380    
381                    return getFileAsStream(
382                            companyId, repositoryId, fileName, StringPool.BLANK);
383            }
384    
385            /**
386             * Returns the file as an {@link InputStream} object.
387             *
388             * @param  companyId the primary key of the company
389             * @param  repositoryId the primary key of the data repository (optionally
390             *         {@link com.liferay.portal.model.CompanyConstants#SYSTEM})
391             * @param  fileName the file's name
392             * @param  versionLabel the file's version label
393             * @return Returns the {@link InputStream} object with the file's name
394             * @throws PortalException if the file's information was invalid
395             * @throws SystemException if a system exception occurred
396             */
397            @Override
398            public abstract InputStream getFileAsStream(
399                            long companyId, long repositoryId, String fileName,
400                            String versionLabel)
401                    throws PortalException, SystemException;
402    
403            /**
404             * Returns all files of the directory.
405             *
406             * @param  companyId the primary key of the company
407             * @param  repositoryId the primary key of the data repository (optionally
408             *         {@link com.liferay.portal.model.CompanyConstants#SYSTEM})
409             * @param  dirName the directory's name
410             * @return Returns all files of the directory
411             * @throws PortalException if the directory's information was invalid
412             * @throws SystemException if a system exception occurred
413             */
414            @Override
415            public abstract String[] getFileNames(
416                            long companyId, long repositoryId, String dirName)
417                    throws PortalException, SystemException;
418    
419            /**
420             * Returns the size of the file.
421             *
422             * @param  companyId the primary key of the company
423             * @param  repositoryId the primary key of the data repository (optionally
424             *         {@link com.liferay.portal.model.CompanyConstants#SYSTEM})
425             * @param  fileName the file's name
426             * @return Returns the size of the file
427             * @throws PortalException if the file's information was invalid
428             * @throws SystemException if a system exception occurred
429             */
430            @Override
431            public abstract long getFileSize(
432                            long companyId, long repositoryId, String fileName)
433                    throws PortalException, SystemException;
434    
435            /**
436             * Returns <code>true</code> if the directory exists.
437             *
438             * @param  companyId the primary key of the company
439             * @param  repositoryId the primary key of the data repository (optionally
440             *         {@link com.liferay.portal.model.CompanyConstants#SYSTEM})
441             * @param  dirName the directory's name
442             * @return <code>true</code> if the directory exists; <code>false</code>
443             *         otherwise
444             * @throws PortalException if the directory's information was invalid
445             * @throws SystemException if a system exception occurred
446             */
447            @Override
448            public abstract boolean hasDirectory(
449                            long companyId, long repositoryId, String dirName)
450                    throws PortalException, SystemException;
451    
452            /**
453             * Returns <code>true</code> if the file exists.
454             *
455             * @param  companyId the primary key of the company
456             * @param  repositoryId the primary key of the data repository (optionally
457             *         {@link com.liferay.portal.model.CompanyConstants#SYSTEM})
458             * @param  fileName the file's name
459             * @return <code>true</code> if the file exists; <code>false</code>
460             *         otherwise
461             * @throws PortalException if the file's information was invalid
462             * @throws SystemException if a system exception occurred
463             */
464            @Override
465            public boolean hasFile(long companyId, long repositoryId, String fileName)
466                    throws PortalException, SystemException {
467    
468                    return hasFile(companyId, repositoryId, fileName, VERSION_DEFAULT);
469            }
470    
471            /**
472             * Returns <code>true</code> if the file exists.
473             *
474             * @param  companyId the primary key of the company
475             * @param  repositoryId the primary key of the data repository (optionally
476             *         {@link com.liferay.portal.model.CompanyConstants#SYSTEM})
477             * @param  fileName the file's name
478             * @param  versionLabel the file's version label
479             * @return <code>true</code> if the file exists; <code>false</code>
480             *         otherwise
481             * @throws PortalException if the file's information was invalid
482             * @throws SystemException if a system exception occurred
483             */
484            @Override
485            public abstract boolean hasFile(
486                            long companyId, long repositoryId, String fileName,
487                            String versionLabel)
488                    throws PortalException, SystemException;
489    
490            /**
491             * Moves an existing directory. Only implemented by {@link
492             * JCRStore#move(String, String)}.
493             *
494             * @param  srcDir the original directory's name
495             * @param  destDir the new directory's name
496             * @throws SystemException if a system exception occurred
497             */
498            @Override
499            public abstract void move(String srcDir, String destDir)
500                    throws SystemException;
501    
502            /**
503             * Moves a file to a new data repository.
504             *
505             * @param  companyId the primary key of the company
506             * @param  repositoryId the primary key of the data repository
507             * @param  newRepositoryId the primary key of the new data repository
508             * @param  fileName the file's name
509             * @throws PortalException if the file's information was invalid
510             * @throws SystemException if a system exception occurred
511             */
512            @Override
513            public abstract void updateFile(
514                            long companyId, long repositoryId, long newRepositoryId,
515                            String fileName)
516                    throws PortalException, SystemException;
517    
518            /**
519             * Updates a file based on a byte array.
520             *
521             * @param  companyId the primary key of the company
522             * @param  repositoryId the primary key of the data repository (optionally
523             *         {@link com.liferay.portal.model.CompanyConstants#SYSTEM})
524             * @param  fileName the file name
525             * @param  versionLabel the file's new version label
526             * @param  bytes the new file's data
527             * @throws PortalException if the file's information was invalid
528             * @throws SystemException if a system exception occurred
529             */
530            @Override
531            public void updateFile(
532                            long companyId, long repositoryId, String fileName,
533                            String versionLabel, byte[] bytes)
534                    throws PortalException, SystemException {
535    
536                    File file = null;
537    
538                    try {
539                            file = FileUtil.createTempFile(bytes);
540    
541                            updateFile(companyId, repositoryId, fileName, versionLabel, file);
542                    }
543                    catch (IOException ioe) {
544                            throw new SystemException("Unable to write temporary file", ioe);
545                    }
546                    finally {
547                            FileUtil.delete(file);
548                    }
549            }
550    
551            /**
552             * Updates a file based on a {@link File} object.
553             *
554             * @param  companyId the primary key of the company
555             * @param  repositoryId the primary key of the data repository (optionally
556             *         {@link com.liferay.portal.model.CompanyConstants#SYSTEM})
557             * @param  fileName the file name
558             * @param  versionLabel the file's new version label
559             * @param  file Name the file name
560             * @throws PortalException if the file's information was invalid
561             * @throws SystemException if a system exception occurred
562             */
563            @Override
564            public void updateFile(
565                            long companyId, long repositoryId, String fileName,
566                            String versionLabel, File file)
567                    throws PortalException, SystemException {
568    
569                    InputStream is = null;
570    
571                    try {
572                            is = new FileInputStream(file);
573    
574                            updateFile(companyId, repositoryId, fileName, versionLabel, is);
575                    }
576                    catch (FileNotFoundException fnfe) {
577                            throw new NoSuchFileException(fileName);
578                    }
579                    finally {
580                            try {
581                                    if (is != null) {
582                                            is.close();
583                                    }
584                            }
585                            catch (IOException ioe) {
586                                    _log.error(ioe);
587                            }
588                    }
589            }
590    
591            /**
592             * Updates a file based on an {@link InputStream} object.
593             *
594             * @param  companyId the primary key of the company
595             * @param  repositoryId the primary key of the data repository (optionally
596             *         {@link com.liferay.portal.model.CompanyConstants#SYSTEM})
597             * @param  fileName the file name
598             * @param  versionLabel the file's new version label
599             * @param  is the new file's data
600             * @throws PortalException if the file's information was invalid
601             * @throws SystemException if a system exception occurred
602             */
603            @Override
604            public abstract void updateFile(
605                            long companyId, long repositoryId, String fileName,
606                            String versionLabel, InputStream is)
607                    throws PortalException, SystemException;
608    
609            /**
610             * Update's a file version label. Similar to {@link #copyFileVersion(long,
611             * long, String, String, String)} except that the old file version is
612             * deleted.
613             *
614             * @param  companyId the primary key of the company
615             * @param  repositoryId the primary key of the data repository (optionally
616             *         {@link com.liferay.portal.model.CompanyConstants#SYSTEM})
617             * @param  fileName the file's name
618             * @param  fromVersionLabel the file's version label
619             * @param  toVersionLabel the file's new version label
620             * @throws PortalException if the file's information was invalid
621             * @throws SystemException if a system exception occurred
622             */
623            @Override
624            public void updateFileVersion(
625                            long companyId, long repositoryId, String fileName,
626                            String fromVersionLabel, String toVersionLabel)
627                    throws PortalException, SystemException {
628    
629                    InputStream is = getFileAsStream(
630                            companyId, repositoryId, fileName, fromVersionLabel);
631    
632                    if (is == null) {
633                            is = new UnsyncByteArrayInputStream(new byte[0]);
634                    }
635    
636                    updateFile(companyId, repositoryId, fileName, toVersionLabel, is);
637    
638                    deleteFile(companyId, repositoryId, fileName, fromVersionLabel);
639            }
640    
641            private static Log _log = LogFactoryUtil.getLog(BaseStore.class);
642    
643    }