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