001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.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 Name the file name
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 used
151             * (e.g., {@link FileSystemStore#copyFileVersion(long, long, String, String,
152             * String, String)}).
153             * </p>
154             *
155             * @param  companyId the primary key of the company
156             * @param  repositoryId the primary key of the data repository (optionally
157             *         {@link CompanyConstants#SYSTEM})
158             * @param  fileName the original's file name
159             * @param  fromVersionLabel the original file's version label
160             * @param  toVersionLabel the new version label
161             * @throws PortalException if the file's information was invalid
162             * @throws SystemException if a system exception occurred
163             */
164            public void copyFileVersion(
165                            long companyId, long repositoryId, String fileName,
166                            String fromVersionLabel, String toVersionLabel)
167                    throws PortalException, SystemException {
168    
169                    InputStream is = getFileAsStream(
170                            companyId, repositoryId, fileName, fromVersionLabel);
171    
172                    updateFile(companyId, repositoryId, fileName, toVersionLabel, is);
173            }
174    
175            /**
176             * Deletes a directory.
177             *
178             * @param  companyId the primary key of the company
179             * @param  repositoryId the primary key of the data repository (optionally
180             *         {@link CompanyConstants#SYSTEM})
181             * @param  dirName the directory's name
182             * @throws PortalException if the directory's information was invalid
183             * @throws SystemException if a system exception occurred
184             */
185            public abstract void deleteDirectory(
186                            long companyId, long repositoryId, String dirName)
187                    throws PortalException, SystemException;
188    
189            /**
190             * Deletes a file. If a file has multiple versions, all versions will be
191             * deleted.
192             *
193             * @param  companyId the primary key of the company
194             * @param  repositoryId the primary key of the data repository (optionally
195             *         {@link CompanyConstants#SYSTEM})
196             * @param  fileName the file's name
197             * @throws PortalException if the file's information was invalid
198             * @throws SystemException if a system exception occurred
199             */
200            public abstract void deleteFile(
201                            long companyId, long repositoryId, String fileName)
202                    throws PortalException, SystemException;
203    
204            /**
205             * Deletes a file at a particular version.
206             *
207             * @param  companyId the primary key of the company
208             * @param  repositoryId the primary key of the data repository (optionally
209             *         {@link CompanyConstants#SYSTEM})
210             * @param  fileName the file's name
211             * @param  versionLabel the file's version label
212             * @throws PortalException if the file's information was invalid
213             * @throws SystemException if a system exception occurred
214             */
215            public abstract void deleteFile(
216                            long companyId, long repositoryId, String fileName,
217                            String versionLabel)
218                    throws PortalException, SystemException;
219    
220            /**
221             * Returns the file as a {@link File} object.
222             *
223             * <p>
224             * This method is useful when optimizing low-level file operations like
225             * copy. The client must not delete or change the returned {@link File}
226             * object in any way. This method is only supported in certain stores. If
227             * not supported, this method will throw an {@link
228             * UnsupportedOperationException}.
229             * </p>
230             *
231             * @param  companyId the primary key of the company
232             * @param  repositoryId the primary key of the data repository (optionally
233             *         {@link CompanyConstants#SYSTEM})
234             * @param  fileName the file's name
235             * @return Returns the {@link File} object with the file's name
236             * @throws PortalException if the file's information was invalid
237             * @throws SystemException if a system exception occurred
238             */
239            public File getFile(long companyId, long repositoryId, String fileName)
240                    throws PortalException, SystemException {
241    
242                    return getFile(companyId, repositoryId, fileName, StringPool.BLANK);
243            }
244    
245            /**
246             * Returns the file as a {@link File} object.
247             *
248             * <p>
249             * This method is useful when optimizing low-level file operations like
250             * copy. The client must not delete or change the returned {@link File}
251             * object in any way. This method is only supported in certain stores. If
252             * not supported, this method will throw an {@link
253             * UnsupportedOperationException}.
254             * </p>
255             *
256             * <p>
257             * This method should be overrided if a more optimized approach can be used
258             * (e.g., {@link FileSystemStore#getFile(long, long, String, String)}).
259             * </p>
260             *
261             * @param  companyId the primary key of the company
262             * @param  repositoryId the primary key of the data repository (optionally
263             *         {@link CompanyConstants#SYSTEM})
264             * @param  fileName the file's name
265             * @param  versionLabel the file's version label
266             * @return Returns the {@link File} object with the file's name
267             * @throws PortalException if the file's information was invalid
268             * @throws SystemException if a system exception occurred
269             */
270            public File getFile(
271                            long companyId, long repositoryId, String fileName,
272                            String versionLabel)
273                    throws PortalException, SystemException {
274    
275                    throw new UnsupportedOperationException();
276            }
277    
278            /**
279             * Returns the file as a byte array.
280             *
281             * @param  companyId the primary key of the company
282             * @param  repositoryId the primary key of the data repository (optionally
283             *         {@link CompanyConstants#SYSTEM})
284             * @param  fileName the file's name
285             * @return Returns the byte array with the file's name
286             * @throws PortalException if the file's information was invalid
287             * @throws SystemException if a system exception occurred
288             */
289            public byte[] getFileAsBytes(
290                            long companyId, long repositoryId, String fileName)
291                    throws PortalException, SystemException {
292    
293                    byte[] bytes = null;
294    
295                    try {
296                            InputStream is = getFileAsStream(companyId, repositoryId, fileName);
297    
298                            bytes = FileUtil.getBytes(is);
299                    }
300                    catch (IOException ioe) {
301                            throw new SystemException(ioe);
302                    }
303    
304                    return bytes;
305            }
306    
307            /**
308             * Returns the file as a byte array.
309             *
310             * @param  companyId the primary key of the company
311             * @param  repositoryId the primary key of the data repository (optionally
312             *         {@link CompanyConstants#SYSTEM})
313             * @param  fileName the file's name
314             * @param  versionLabel the file's version label
315             * @return Returns the byte array with the file's name
316             * @throws PortalException if the file's information was invalid
317             * @throws SystemException if a system exception occurred
318             */
319            public byte[] getFileAsBytes(
320                            long companyId, long repositoryId, String fileName,
321                            String versionLabel)
322                    throws PortalException, SystemException {
323    
324                    byte[] bytes = null;
325    
326                    try {
327                            InputStream is = getFileAsStream(
328                                    companyId, repositoryId, fileName, versionLabel);
329    
330                            bytes = FileUtil.getBytes(is);
331                    }
332                    catch (IOException ioe) {
333                            throw new SystemException(ioe);
334                    }
335    
336                    return bytes;
337            }
338    
339            /**
340             * Returns the file as an {@link InputStream} object.
341             *
342             * @param  companyId the primary key of the company
343             * @param  repositoryId the primary key of the data repository (optionally
344             *         {@link CompanyConstants#SYSTEM})
345             * @param  fileName the file's name
346             * @return Returns the {@link InputStream} object with the file's name
347             * @throws PortalException if the file's information was invalid
348             * @throws SystemException if a system exception occurred
349             */
350            public InputStream getFileAsStream(
351                            long companyId, long repositoryId, String fileName)
352                    throws PortalException, SystemException {
353    
354                    return getFileAsStream(companyId, repositoryId, fileName,
355                            StringPool.BLANK);
356            }
357    
358            /**
359             * Returns the file as an {@link InputStream} object.
360             *
361             * @param  companyId the primary key of the company
362             * @param  repositoryId the primary key of the data repository (optionally
363             *         {@link CompanyConstants#SYSTEM})
364             * @param  fileName the file's name
365             * @param  versionLabel the file's version label
366             * @return Returns the {@link InputStream} object with the file's name
367             * @throws PortalException if the file's information was invalid
368             * @throws SystemException if a system exception occurred
369             */
370            public abstract InputStream getFileAsStream(
371                            long companyId, long repositoryId, String fileName,
372                            String versionLabel)
373                    throws PortalException, SystemException;
374    
375            /**
376             * Returns all files of the directory.
377             *
378             * @param  companyId the primary key of the company
379             * @param  repositoryId the primary key of the data repository (optionally
380             *         {@link CompanyConstants#SYSTEM})
381             * @param  dirName the directory's name
382             * @return Returns all files of the directory
383             * @throws PortalException if the directory's information was invalid
384             * @throws SystemException if a system exception occurred
385             */
386            public abstract String[] getFileNames(
387                            long companyId, long repositoryId, String dirName)
388                    throws PortalException, SystemException;
389    
390            /**
391             * Returns the size of the file.
392             *
393             * @param  companyId the primary key of the company
394             * @param  repositoryId the primary key of the data repository (optionally
395             *         {@link CompanyConstants#SYSTEM})
396             * @param  fileName the file's name
397             * @return Returns the size of the file
398             * @throws PortalException if the file's information was invalid
399             * @throws SystemException if a system exception occurred
400             */
401            public abstract long getFileSize(
402                            long companyId, long repositoryId, String fileName)
403                    throws PortalException, SystemException;
404    
405            /**
406             * Returns <code>true</code> if the directory exists.
407             *
408             * @param  companyId the primary key of the company
409             * @param  repositoryId the primary key of the data repository (optionally
410             *         {@link CompanyConstants#SYSTEM})
411             * @param  dirName the directory's name
412             * @return <code>true</code> if the directory exists; <code>false</code>
413             *         otherwise
414             * @throws PortalException if the directory's information was invalid
415             * @throws SystemException if a system exception occurred
416             */
417            public abstract boolean hasDirectory(
418                            long companyId, long repositoryId, String dirName)
419                    throws PortalException, SystemException;
420    
421            /**
422             * Returns <code>true</code> if the file exists.
423             *
424             * @param  companyId the primary key of the company
425             * @param  repositoryId the primary key of the data repository (optionally
426             *         {@link CompanyConstants#SYSTEM})
427             * @param  fileName the file's name
428             * @return <code>true</code> if the file exists; <code>false</code>
429             *         otherwise
430             * @throws PortalException if the file's information was invalid
431             * @throws SystemException if a system exception occurred
432             */
433            public boolean hasFile(long companyId, long repositoryId, String fileName)
434                    throws PortalException, SystemException {
435    
436                    return hasFile(companyId, repositoryId, fileName, VERSION_DEFAULT);
437            }
438    
439            /**
440             * Returns <code>true</code> if the file exists.
441             *
442             * @param  companyId the primary key of the company
443             * @param  repositoryId the primary key of the data repository (optionally
444             *         {@link CompanyConstants#SYSTEM})
445             * @param  fileName the file's name
446             * @param  versionLabel the file's version label
447             * @return <code>true</code> if the file exists; <code>false</code>
448             *         otherwise
449             * @throws PortalException if the file's information was invalid
450             * @throws SystemException if a system exception occurred
451             */
452            public abstract boolean hasFile(
453                            long companyId, long repositoryId, String fileName,
454                            String versionLabel)
455                    throws PortalException, SystemException;
456    
457            /**
458             * Moves an existing directory. Only implemented by {@link
459             * JCRStore#move(String, String)}.
460             *
461             * @param  srcDir the original directory's name
462             * @param  destDir the new directory's name
463             * @throws SystemException if a system exception occurred
464             */
465            public abstract void move(String srcDir, String destDir)
466                    throws SystemException;
467    
468            /**
469             * Moves a file to a new data repository.
470             *
471             * @param  companyId the primary key of the company
472             * @param  repositoryId the primary key of the data repository
473             * @param  newRepositoryId the primary key of the new data repository
474             * @param  fileName the file's name
475             * @throws PortalException if the file's information was invalid
476             * @throws SystemException if a system exception occurred
477             */
478            public abstract void updateFile(
479                            long companyId, long repositoryId, long newRepositoryId,
480                            String fileName)
481                    throws PortalException, SystemException;
482    
483            /**
484             * Updates a file based on a byte array.
485             *
486             * @param  companyId the primary key of the company
487             * @param  repositoryId the primary key of the data repository (optionally
488             *         {@link CompanyConstants#SYSTEM})
489             * @param  fileName the file name
490             * @param  versionLabel the file's new version label
491             * @param  bytes the new file's data
492             * @throws PortalException if the file's information was invalid
493             * @throws SystemException if a system exception occurred
494             */
495            public void updateFile(
496                            long companyId, long repositoryId, String fileName,
497                            String versionLabel, byte[] bytes)
498                    throws PortalException, SystemException {
499    
500                    File file = null;
501    
502                    try {
503                            file = FileUtil.createTempFile(bytes);
504    
505                            updateFile(companyId, repositoryId, fileName, versionLabel, file);
506                    }
507                    catch (IOException ioe) {
508                            throw new SystemException("Unable to write temporary file", ioe);
509                    }
510                    finally {
511                            FileUtil.delete(file);
512                    }
513            }
514    
515            /**
516             * Updates a file based on a {@link File} object.
517             *
518             * @param  companyId the primary key of the company
519             * @param  repositoryId the primary key of the data repository (optionally
520             *         {@link CompanyConstants#SYSTEM})
521             * @param  fileName the file name
522             * @param  versionLabel the file's new version label
523             * @param  file Name the file name
524             * @throws PortalException if the file's information was invalid
525             * @throws SystemException if a system exception occurred
526             */
527            public void updateFile(
528                            long companyId, long repositoryId, String fileName,
529                            String versionLabel, File file)
530                    throws PortalException, SystemException {
531    
532                    InputStream is = null;
533    
534                    try {
535                            is = new FileInputStream(file);
536    
537                            updateFile(companyId, repositoryId, fileName, versionLabel, is);
538                    }
539                    catch (FileNotFoundException fnfe) {
540                            throw new NoSuchFileException(fileName);
541                    }
542                    finally {
543                            try {
544                                    if (is != null) {
545                                            is.close();
546                                    }
547                            }
548                            catch (IOException ioe) {
549                                    _log.error(ioe);
550                            }
551                    }
552            }
553    
554            /**
555             * Updates a file based on an {@link InputStream} object.
556             *
557             * @param  companyId the primary key of the company
558             * @param  repositoryId the primary key of the data repository (optionally
559             *         {@link CompanyConstants#SYSTEM})
560             * @param  fileName the file name
561             * @param  versionLabel the file's new version label
562             * @param  is the new file's data
563             * @throws PortalException if the file's information was invalid
564             * @throws SystemException if a system exception occurred
565             */
566            public abstract void updateFile(
567                            long companyId, long repositoryId, String fileName,
568                            String versionLabel, InputStream is)
569                    throws PortalException, SystemException;
570    
571            /**
572             * Update's a file version label. Similar to {@link #copyFileVersion(long,
573             * long, String, String, String, String)} except that the old file version
574             * is deleted.
575             *
576             * @param  companyId the primary key of the company
577             * @param  repositoryId the primary key of the data repository (optionally
578             *         {@link CompanyConstants#SYSTEM})
579             * @param  fileName the file's name
580             * @param  fromVersionLabel the file's version label
581             * @param  toVersionLabel the file's new version label
582             * @throws PortalException if the file's information was invalid
583             * @throws SystemException if a system exception occurred
584             */
585            public void updateFileVersion(
586                            long companyId, long repositoryId, String fileName,
587                            String fromVersionLabel, String toVersionLabel)
588                    throws PortalException, SystemException {
589    
590                    InputStream is = getFileAsStream(
591                            companyId, repositoryId, fileName, fromVersionLabel);
592    
593                    updateFile(companyId, repositoryId, fileName, toVersionLabel, is);
594    
595                    deleteFile(companyId, repositoryId, fileName, fromVersionLabel);
596            }
597    
598            private static Log _log = LogFactoryUtil.getLog(BaseStore.class);
599    
600    }