/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.document.library.kernel.store; import com.liferay.document.library.kernel.exception.NoSuchFileException; import com.liferay.portal.kernel.exception.PortalException; import com.liferay.portal.kernel.exception.SystemException; import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayInputStream; import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.util.FileUtil; import com.liferay.portal.kernel.util.StringBundler; import com.liferay.portal.kernel.util.StringPool; import com.liferay.portal.kernel.util.Validator; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; /** * The abstract base class for all file store implementations. Most, if not all * implementations should extend this class. * * @author Brian Wing Shun Chan * @author Alexander Chow * @author Edward Han */ public abstract class BaseStore implements Store { /** * Adds a directory. * * @param companyId the primary key of the company * @param repositoryId the primary key of the data repository (optionally * {@link com.liferay.portal.kernel.model.CompanyConstants#SYSTEM}) * @param dirName the directory's name */ @Override public abstract void addDirectory( long companyId, long repositoryId, String dirName); /** * Adds a file based on a byte array. * * @param companyId the primary key of the company * @param repositoryId the primary key of the data repository (optionally * {@link com.liferay.portal.kernel.model.CompanyConstants#SYSTEM}) * @param fileName the file name * @param bytes the files's data */ @Override public void addFile( long companyId, long repositoryId, String fileName, byte[] bytes) throws PortalException { try (UnsyncByteArrayInputStream unsyncByteArrayInputStream = new UnsyncByteArrayInputStream(bytes)) { addFile( companyId, repositoryId, fileName, unsyncByteArrayInputStream); } catch (IOException ioe) { throw new SystemException("Unable to read bytes", ioe); } } /** * Adds a file based on a {@link File} object. * * @param companyId the primary key of the company * @param repositoryId the primary key of the data repository (optionally * {@link com.liferay.portal.kernel.model.CompanyConstants#SYSTEM}) * @param fileName the file name * @param file Name the file name */ @Override public void addFile( long companyId, long repositoryId, String fileName, File file) throws PortalException { try (InputStream is = new FileInputStream(file)) { addFile(companyId, repositoryId, fileName, is); } catch (FileNotFoundException fnfe) { throw new SystemException(fnfe); } catch (IOException ioe) { _log.error(ioe); } } /** * Adds a file based on an {@link InputStream} object. * * @param companyId the primary key of the company * @param repositoryId the primary key of the data repository (optionally * {@link com.liferay.portal.kernel.model.CompanyConstants#SYSTEM}) * @param fileName the file name * @param is the files's data */ @Override public abstract void addFile( long companyId, long repositoryId, String fileName, InputStream is) throws PortalException; /** * Ensures company's root directory exists. Only implemented by {@link * JCRStore#checkRoot(long)}. * * @param companyId the primary key of the company */ @Override public abstract void checkRoot(long companyId); /** * Creates a new copy of the file version. * * <p> * This method should be overrided if a more optimized approach can be used * (e.g., {@link FileSystemStore#copyFileVersion(long, long, String, String, * String)}). * </p> * * @param companyId the primary key of the company * @param repositoryId the primary key of the data repository (optionally * {@link com.liferay.portal.kernel.model.CompanyConstants#SYSTEM}) * @param fileName the original's file name * @param fromVersionLabel the original file's version label * @param toVersionLabel the new version label */ @Override public void copyFileVersion( long companyId, long repositoryId, String fileName, String fromVersionLabel, String toVersionLabel) throws PortalException { InputStream is = getFileAsStream( companyId, repositoryId, fileName, fromVersionLabel); if (is == null) { is = new UnsyncByteArrayInputStream(new byte[0]); } updateFile(companyId, repositoryId, fileName, toVersionLabel, is); } /** * Deletes a directory. * * @param companyId the primary key of the company * @param repositoryId the primary key of the data repository (optionally * {@link com.liferay.portal.kernel.model.CompanyConstants#SYSTEM}) * @param dirName the directory's name */ @Override public abstract void deleteDirectory( long companyId, long repositoryId, String dirName); /** * Deletes a file. If a file has multiple versions, all versions will be * deleted. * * @param companyId the primary key of the company * @param repositoryId the primary key of the data repository (optionally * {@link com.liferay.portal.kernel.model.CompanyConstants#SYSTEM}) * @param fileName the file's name */ @Override public abstract void deleteFile( long companyId, long repositoryId, String fileName); /** * Deletes a file at a particular version. * * @param companyId the primary key of the company * @param repositoryId the primary key of the data repository (optionally * {@link com.liferay.portal.kernel.model.CompanyConstants#SYSTEM}) * @param fileName the file's name * @param versionLabel the file's version label */ @Override public abstract void deleteFile( long companyId, long repositoryId, String fileName, String versionLabel); /** * Returns the file as a {@link File} object. * * <p> * This method is useful when optimizing low-level file operations like * copy. The client must not delete or change the returned {@link File} * object in any way. This method is only supported in certain stores. If * not supported, this method will throw an {@link * UnsupportedOperationException}. * </p> * * @param companyId the primary key of the company * @param repositoryId the primary key of the data repository (optionally * {@link com.liferay.portal.kernel.model.CompanyConstants#SYSTEM}) * @param fileName the file's name * @return Returns the {@link File} object with the file's name */ @Override public File getFile(long companyId, long repositoryId, String fileName) throws PortalException { return getFile(companyId, repositoryId, fileName, StringPool.BLANK); } /** * Returns the file as a {@link File} object. * * <p> * This method is useful when optimizing low-level file operations like * copy. The client must not delete or change the returned {@link File} * object in any way. This method is only supported in certain stores. If * not supported, this method will throw an {@link * UnsupportedOperationException}. * </p> * * <p> * This method should be overrided if a more optimized approach can be used * (e.g., {@link FileSystemStore#getFile(long, long, String, String)}). * </p> * * @param companyId the primary key of the company * @param repositoryId the primary key of the data repository (optionally * {@link com.liferay.portal.kernel.model.CompanyConstants#SYSTEM}) * @param fileName the file's name * @param versionLabel the file's version label * @return Returns the {@link File} object with the file's name * @throws PortalException */ @Override public File getFile( long companyId, long repositoryId, String fileName, String versionLabel) throws PortalException { throw new UnsupportedOperationException(); } /** * Returns the file as a byte array. * * @param companyId the primary key of the company * @param repositoryId the primary key of the data repository (optionally * {@link com.liferay.portal.kernel.model.CompanyConstants#SYSTEM}) * @param fileName the file's name * @return Returns the byte array with the file's name */ @Override public byte[] getFileAsBytes( long companyId, long repositoryId, String fileName) throws PortalException { try { InputStream is = getFileAsStream(companyId, repositoryId, fileName); return FileUtil.getBytes(is); } catch (IOException ioe) { throw new SystemException(ioe); } } /** * Returns the file as a byte array. * * @param companyId the primary key of the company * @param repositoryId the primary key of the data repository (optionally * {@link com.liferay.portal.kernel.model.CompanyConstants#SYSTEM}) * @param fileName the file's name * @param versionLabel the file's version label * @return Returns the byte array with the file's name */ @Override public byte[] getFileAsBytes( long companyId, long repositoryId, String fileName, String versionLabel) throws PortalException { try { InputStream is = getFileAsStream( companyId, repositoryId, fileName, versionLabel); return FileUtil.getBytes(is); } catch (IOException ioe) { throw new SystemException(ioe); } } /** * Returns the file as an {@link InputStream} object. * * @param companyId the primary key of the company * @param repositoryId the primary key of the data repository (optionally * {@link com.liferay.portal.kernel.model.CompanyConstants#SYSTEM}) * @param fileName the file's name * @return Returns the {@link InputStream} object with the file's name */ @Override public InputStream getFileAsStream( long companyId, long repositoryId, String fileName) throws PortalException { return getFileAsStream( companyId, repositoryId, fileName, StringPool.BLANK); } /** * Returns the file as an {@link InputStream} object. * * @param companyId the primary key of the company * @param repositoryId the primary key of the data repository (optionally * {@link com.liferay.portal.kernel.model.CompanyConstants#SYSTEM}) * @param fileName the file's name * @param versionLabel the file's version label * @return Returns the {@link InputStream} object with the file's name */ @Override public abstract InputStream getFileAsStream( long companyId, long repositoryId, String fileName, String versionLabel) throws PortalException; /** * Returns all files of the directory. * * @param companyId the primary key of the company * @param repositoryId the primary key of the data repository (optionally * {@link com.liferay.portal.kernel.model.CompanyConstants#SYSTEM}) * @param dirName the directory's name * @return Returns all files of the directory */ @Override public abstract String[] getFileNames( long companyId, long repositoryId, String dirName); /** * Returns the size of the file. * * @param companyId the primary key of the company * @param repositoryId the primary key of the data repository (optionally * {@link com.liferay.portal.kernel.model.CompanyConstants#SYSTEM}) * @param fileName the file's name * @return Returns the size of the file */ @Override public abstract long getFileSize( long companyId, long repositoryId, String fileName) throws PortalException; /** * Returns <code>true</code> if the directory exists. * * @param companyId the primary key of the company * @param repositoryId the primary key of the data repository (optionally * {@link com.liferay.portal.kernel.model.CompanyConstants#SYSTEM}) * @param dirName the directory's name * @return <code>true</code> if the directory exists; <code>false</code> * otherwise */ @Override public abstract boolean hasDirectory( long companyId, long repositoryId, String dirName); /** * Returns <code>true</code> if the file exists. * * @param companyId the primary key of the company * @param repositoryId the primary key of the data repository (optionally * {@link com.liferay.portal.kernel.model.CompanyConstants#SYSTEM}) * @param fileName the file's name * @return <code>true</code> if the file exists; <code>false</code> * otherwise */ @Override public boolean hasFile(long companyId, long repositoryId, String fileName) { return hasFile(companyId, repositoryId, fileName, VERSION_DEFAULT); } /** * Returns <code>true</code> if the file exists. * * @param companyId the primary key of the company * @param repositoryId the primary key of the data repository (optionally * {@link com.liferay.portal.kernel.model.CompanyConstants#SYSTEM}) * @param fileName the file's name * @param versionLabel the file's version label * @return <code>true</code> if the file exists; <code>false</code> * otherwise */ @Override public abstract boolean hasFile( long companyId, long repositoryId, String fileName, String versionLabel); /** * Moves an existing directory. Only implemented by {@link * JCRStore#move(String, String)}. * * @param srcDir the original directory's name * @param destDir the new directory's name */ @Override public void move(String srcDir, String destDir) { } /** * Moves a file to a new data repository. * * @param companyId the primary key of the company * @param repositoryId the primary key of the data repository * @param newRepositoryId the primary key of the new data repository * @param fileName the file's name */ @Override public abstract void updateFile( long companyId, long repositoryId, long newRepositoryId, String fileName) throws PortalException; /** * Updates a file based on a byte array. * * @param companyId the primary key of the company * @param repositoryId the primary key of the data repository (optionally * {@link com.liferay.portal.kernel.model.CompanyConstants#SYSTEM}) * @param fileName the file name * @param versionLabel the file's new version label * @param bytes the new file's data */ @Override public void updateFile( long companyId, long repositoryId, String fileName, String versionLabel, byte[] bytes) throws PortalException { try (UnsyncByteArrayInputStream unsyncByteArrayInputStream = new UnsyncByteArrayInputStream(bytes)) { updateFile( companyId, repositoryId, fileName, versionLabel, unsyncByteArrayInputStream); } catch (IOException ioe) { throw new SystemException("Unable to read bytes", ioe); } } /** * Updates a file based on a {@link File} object. * * @param companyId the primary key of the company * @param repositoryId the primary key of the data repository (optionally * {@link com.liferay.portal.kernel.model.CompanyConstants#SYSTEM}) * @param fileName the file name * @param versionLabel the file's new version label * @param file Name the file name */ @Override public void updateFile( long companyId, long repositoryId, String fileName, String versionLabel, File file) throws PortalException { try (InputStream is = new FileInputStream(file)) { updateFile(companyId, repositoryId, fileName, versionLabel, is); } catch (FileNotFoundException fnfe) { throw new NoSuchFileException( companyId, repositoryId, fileName, versionLabel, fnfe); } catch (IOException ioe) { _log.error(ioe); } } /** * Updates a file based on an {@link InputStream} object. * * @param companyId the primary key of the company * @param repositoryId the primary key of the data repository (optionally * {@link com.liferay.portal.kernel.model.CompanyConstants#SYSTEM}) * @param fileName the file name * @param versionLabel the file's new version label * @param is the new file's data */ @Override public abstract void updateFile( long companyId, long repositoryId, String fileName, String versionLabel, InputStream is) throws PortalException; /** * Update's a file version label. Similar to {@link #copyFileVersion(long, * long, String, String, String)} except that the old file version is * deleted. * * @param companyId the primary key of the company * @param repositoryId the primary key of the data repository (optionally * {@link com.liferay.portal.kernel.model.CompanyConstants#SYSTEM}) * @param fileName the file's name * @param fromVersionLabel the file's version label * @param toVersionLabel the file's new version label */ @Override public void updateFileVersion( long companyId, long repositoryId, String fileName, String fromVersionLabel, String toVersionLabel) throws PortalException { InputStream is = getFileAsStream( companyId, repositoryId, fileName, fromVersionLabel); if (is == null) { is = new UnsyncByteArrayInputStream(new byte[0]); } updateFile(companyId, repositoryId, fileName, toVersionLabel, is); deleteFile(companyId, repositoryId, fileName, fromVersionLabel); } protected void logFailedDeletion( long companyId, long repositoryId, String fileName) { logFailedDeletion(companyId, repositoryId, fileName, null, null); } protected void logFailedDeletion( long companyId, long repositoryId, String fileName, Exception exception) { logFailedDeletion(companyId, repositoryId, fileName, null, exception); } protected void logFailedDeletion( long companyId, long repositoryId, String fileName, String versionLabel) { logFailedDeletion( companyId, repositoryId, fileName, versionLabel, null); } protected void logFailedDeletion( long companyId, long repositoryId, String fileName, String versionLabel, Exception cause) { if ((_log.isWarnEnabled() && (cause != null)) || (_log.isDebugEnabled() && (cause == null))) { StringBundler sb = new StringBundler(9); sb.append("Unable to delete file {companyId="); sb.append(companyId); sb.append(", repositoryId="); sb.append(repositoryId); sb.append(", fileName="); sb.append(fileName); if (Validator.isNotNull(versionLabel)) { sb.append(", versionLabel="); sb.append(versionLabel); } sb.append("} because it does not exist"); if (_log.isWarnEnabled() && (cause != null)) { _log.warn(sb.toString(), cause); } if (_log.isDebugEnabled() && (cause == null)) { _log.debug(sb.toString()); } } } private static final Log _log = LogFactoryUtil.getLog(BaseStore.class); }