001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.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             * @throws SystemException if a system exception occurred
051             */
052            public abstract void addDirectory(
053                            long companyId, long repositoryId, String dirName)
054                    throws PortalException, SystemException;
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             * @throws SystemException if a system exception occurred
066             */
067            public void addFile(
068                            long companyId, long repositoryId, String fileName, byte[] bytes)
069                    throws PortalException, SystemException {
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             * @throws SystemException if a system exception occurred
096             */
097            public void addFile(
098                            long companyId, long repositoryId, String fileName, File file)
099                    throws PortalException, SystemException {
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             * @throws SystemException if a system exception occurred
133             */
134            public abstract void addFile(
135                            long companyId, long repositoryId, String fileName, InputStream is)
136                    throws PortalException, SystemException;
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             * @throws SystemException if a system exception occurred
144             */
145            public abstract void checkRoot(long companyId) throws SystemException;
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             * @throws SystemException if a system exception occurred
164             */
165            public void copyFileVersion(
166                            long companyId, long repositoryId, String fileName,
167                            String fromVersionLabel, String toVersionLabel)
168                    throws PortalException, SystemException {
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             * @throws SystemException if a system exception occurred
189             */
190            public abstract void deleteDirectory(
191                            long companyId, long repositoryId, String dirName)
192                    throws PortalException, SystemException;
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             * @throws SystemException if a system exception occurred
204             */
205            public abstract void deleteFile(
206                            long companyId, long repositoryId, String fileName)
207                    throws PortalException, SystemException;
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             * @throws SystemException if a system exception occurred
219             */
220            public abstract void deleteFile(
221                            long companyId, long repositoryId, String fileName,
222                            String versionLabel)
223                    throws PortalException, SystemException;
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             * @throws SystemException if a system exception occurred
243             */
244            public File getFile(long companyId, long repositoryId, String fileName)
245                    throws PortalException, SystemException {
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             * @throws SystemException if a system exception occurred
274             */
275            public File getFile(
276                            long companyId, long repositoryId, String fileName,
277                            String versionLabel)
278                    throws PortalException, SystemException {
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             * @throws SystemException if a system exception occurred
293             */
294            public byte[] getFileAsBytes(
295                            long companyId, long repositoryId, String fileName)
296                    throws PortalException, SystemException {
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             * @throws SystemException if a system exception occurred
323             */
324            public byte[] getFileAsBytes(
325                            long companyId, long repositoryId, String fileName,
326                            String versionLabel)
327                    throws PortalException, SystemException {
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             * @throws SystemException if a system exception occurred
354             */
355            public InputStream getFileAsStream(
356                            long companyId, long repositoryId, String fileName)
357                    throws PortalException, SystemException {
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             * @throws SystemException if a system exception occurred
374             */
375            public abstract InputStream getFileAsStream(
376                            long companyId, long repositoryId, String fileName,
377                            String versionLabel)
378                    throws PortalException, SystemException;
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             * @throws SystemException if a system exception occurred
390             */
391            public abstract String[] getFileNames(
392                            long companyId, long repositoryId, String dirName)
393                    throws PortalException, SystemException;
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             * @throws SystemException if a system exception occurred
405             */
406            public abstract long getFileSize(
407                            long companyId, long repositoryId, String fileName)
408                    throws PortalException, SystemException;
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             * @throws SystemException if a system exception occurred
421             */
422            public abstract boolean hasDirectory(
423                            long companyId, long repositoryId, String dirName)
424                    throws PortalException, SystemException;
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             * @throws SystemException if a system exception occurred
437             */
438            public boolean hasFile(long companyId, long repositoryId, String fileName)
439                    throws PortalException, SystemException {
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             * @throws SystemException if a system exception occurred
456             */
457            public abstract boolean hasFile(
458                            long companyId, long repositoryId, String fileName,
459                            String versionLabel)
460                    throws PortalException, SystemException;
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             * @throws SystemException if a system exception occurred
469             */
470            public abstract void move(String srcDir, String destDir)
471                    throws SystemException;
472    
473            /**
474             * Moves a file to a new data repository.
475             *
476             * @param  companyId the primary key of the company
477             * @param  repositoryId the primary key of the data repository
478             * @param  newRepositoryId the primary key of the new data repository
479             * @param  fileName the file's name
480             * @throws PortalException if the file's information was invalid
481             * @throws SystemException if a system exception occurred
482             */
483            public abstract void updateFile(
484                            long companyId, long repositoryId, long newRepositoryId,
485                            String fileName)
486                    throws PortalException, SystemException;
487    
488            /**
489             * Updates a file based on a byte array.
490             *
491             * @param  companyId the primary key of the company
492             * @param  repositoryId the primary key of the data repository (optionally
493             *         {@link com.liferay.portal.model.CompanyConstants#SYSTEM})
494             * @param  fileName the file name
495             * @param  versionLabel the file's new version label
496             * @param  bytes the new file's data
497             * @throws PortalException if the file's information was invalid
498             * @throws SystemException if a system exception occurred
499             */
500            public void updateFile(
501                            long companyId, long repositoryId, String fileName,
502                            String versionLabel, byte[] bytes)
503                    throws PortalException, SystemException {
504    
505                    File file = null;
506    
507                    try {
508                            file = FileUtil.createTempFile(bytes);
509    
510                            updateFile(companyId, repositoryId, fileName, versionLabel, file);
511                    }
512                    catch (IOException ioe) {
513                            throw new SystemException("Unable to write temporary file", ioe);
514                    }
515                    finally {
516                            FileUtil.delete(file);
517                    }
518            }
519    
520            /**
521             * Updates a file based on a {@link File} object.
522             *
523             * @param  companyId the primary key of the company
524             * @param  repositoryId the primary key of the data repository (optionally
525             *         {@link com.liferay.portal.model.CompanyConstants#SYSTEM})
526             * @param  fileName the file name
527             * @param  versionLabel the file's new version label
528             * @param  file Name the file name
529             * @throws PortalException if the file's information was invalid
530             * @throws SystemException if a system exception occurred
531             */
532            public void updateFile(
533                            long companyId, long repositoryId, String fileName,
534                            String versionLabel, File file)
535                    throws PortalException, SystemException {
536    
537                    InputStream is = null;
538    
539                    try {
540                            is = new FileInputStream(file);
541    
542                            updateFile(companyId, repositoryId, fileName, versionLabel, is);
543                    }
544                    catch (FileNotFoundException fnfe) {
545                            throw new NoSuchFileException(fileName);
546                    }
547                    finally {
548                            try {
549                                    if (is != null) {
550                                            is.close();
551                                    }
552                            }
553                            catch (IOException ioe) {
554                                    _log.error(ioe);
555                            }
556                    }
557            }
558    
559            /**
560             * Updates a file based on an {@link InputStream} object.
561             *
562             * @param  companyId the primary key of the company
563             * @param  repositoryId the primary key of the data repository (optionally
564             *         {@link com.liferay.portal.model.CompanyConstants#SYSTEM})
565             * @param  fileName the file name
566             * @param  versionLabel the file's new version label
567             * @param  is the new file's data
568             * @throws PortalException if the file's information was invalid
569             * @throws SystemException if a system exception occurred
570             */
571            public abstract void updateFile(
572                            long companyId, long repositoryId, String fileName,
573                            String versionLabel, InputStream is)
574                    throws PortalException, SystemException;
575    
576            /**
577             * Update's a file version label. Similar to {@link #copyFileVersion(long,
578             * long, String, String, String)} except that the old file version is
579             * deleted.
580             *
581             * @param  companyId the primary key of the company
582             * @param  repositoryId the primary key of the data repository (optionally
583             *         {@link com.liferay.portal.model.CompanyConstants#SYSTEM})
584             * @param  fileName the file's name
585             * @param  fromVersionLabel the file's version label
586             * @param  toVersionLabel the file's new version label
587             * @throws PortalException if the file's information was invalid
588             * @throws SystemException if a system exception occurred
589             */
590            public void updateFileVersion(
591                            long companyId, long repositoryId, String fileName,
592                            String fromVersionLabel, String toVersionLabel)
593                    throws PortalException, SystemException {
594    
595                    InputStream is = getFileAsStream(
596                            companyId, repositoryId, fileName, fromVersionLabel);
597    
598                    if (is == null) {
599                            is = new UnsyncByteArrayInputStream(new byte[0]);
600                    }
601    
602                    updateFile(companyId, repositoryId, fileName, toVersionLabel, is);
603    
604                    deleteFile(companyId, repositoryId, fileName, fromVersionLabel);
605            }
606    
607            private static Log _log = LogFactoryUtil.getLog(BaseStore.class);
608    
609    }