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