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