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