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