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