001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.commons.compress.archivers.sevenz; 020 021import java.nio.file.attribute.FileTime; 022import java.util.Arrays; 023import java.util.Collections; 024import java.util.Date; 025import java.util.Iterator; 026import java.util.LinkedList; 027import java.util.Objects; 028 029import org.apache.commons.compress.archivers.ArchiveEntry; 030import org.apache.commons.io.file.attribute.FileTimes; 031 032/** 033 * An entry in a 7z archive. 034 * 035 * @NotThreadSafe 036 * @since 1.6 037 */ 038public class SevenZArchiveEntry implements ArchiveEntry { 039 040 static final SevenZArchiveEntry[] EMPTY_SEVEN_Z_ARCHIVE_ENTRY_ARRAY = {}; 041 042 /** 043 * Converts Java time to NTFS time. 044 * 045 * @param date the Java time 046 * @return the NTFS time 047 * @deprecated Use {@link FileTimes#toNtfsTime(Date)} instead. 048 * @see FileTimes#toNtfsTime(Date) 049 */ 050 @Deprecated 051 public static long javaTimeToNtfsTime(final Date date) { 052 return FileTimes.toNtfsTime(date); 053 } 054 055 /** 056 * Converts NTFS time (100 nanosecond units since 1 January 1601) to Java time. 057 * 058 * @param ntfsTime the NTFS time in 100 nanosecond units 059 * @return the Java time 060 * @deprecated Use {@link FileTimes#ntfsTimeToDate(long)} instead. 061 * @see FileTimes#ntfsTimeToDate(long) 062 */ 063 @Deprecated 064 public static Date ntfsTimeToJavaTime(final long ntfsTime) { 065 return FileTimes.ntfsTimeToDate(ntfsTime); 066 } 067 068 private String name; 069 private boolean hasStream; 070 private boolean isDirectory; 071 private boolean isAntiItem; 072 private boolean hasCreationDate; 073 private boolean hasLastModifiedDate; 074 private boolean hasAccessDate; 075 private FileTime creationDate; 076 private FileTime lastModifiedDate; 077 private FileTime accessDate; 078 private boolean hasWindowsAttributes; 079 private int windowsAttributes; 080 private boolean hasCrc; 081 private long crc; 082 private long compressedCrc; 083 private long size; 084 private long compressedSize; 085 private Iterable<? extends SevenZMethodConfiguration> contentMethods; 086 087 /** 088 * Constructs a new instance. 089 */ 090 public SevenZArchiveEntry() { 091 } 092 093 @Override 094 public boolean equals(final Object obj) { 095 if (this == obj) { 096 return true; 097 } 098 if (obj == null || getClass() != obj.getClass()) { 099 return false; 100 } 101 final SevenZArchiveEntry other = (SevenZArchiveEntry) obj; 102 return Objects.equals(name, other.name) && hasStream == other.hasStream && isDirectory == other.isDirectory && isAntiItem == other.isAntiItem 103 && hasCreationDate == other.hasCreationDate && hasLastModifiedDate == other.hasLastModifiedDate && hasAccessDate == other.hasAccessDate 104 && Objects.equals(creationDate, other.creationDate) && Objects.equals(lastModifiedDate, other.lastModifiedDate) 105 && Objects.equals(accessDate, other.accessDate) && hasWindowsAttributes == other.hasWindowsAttributes 106 && windowsAttributes == other.windowsAttributes && hasCrc == other.hasCrc && crc == other.crc && compressedCrc == other.compressedCrc 107 && size == other.size && compressedSize == other.compressedSize && equalSevenZMethods(contentMethods, other.contentMethods); 108 } 109 110 private boolean equalSevenZMethods(final Iterable<? extends SevenZMethodConfiguration> c1, final Iterable<? extends SevenZMethodConfiguration> c2) { 111 if (c1 == null) { 112 return c2 == null; 113 } 114 if (c2 == null) { 115 return false; 116 } 117 final Iterator<? extends SevenZMethodConfiguration> i2 = c2.iterator(); 118 for (final SevenZMethodConfiguration element : c1) { 119 if (!i2.hasNext() || !element.equals(i2.next())) { 120 return false; 121 } 122 } 123 return !i2.hasNext(); 124 } 125 126 /** 127 * Gets the access date. This is equivalent to {@link SevenZArchiveEntry#getAccessTime()}, but precision is truncated to milliseconds. 128 * 129 * @throws UnsupportedOperationException if the entry hasn't got an access date. 130 * @return the access date 131 * @see SevenZArchiveEntry#getAccessTime() 132 */ 133 public Date getAccessDate() { 134 return FileTimes.toDate(getAccessTime()); 135 } 136 137 /** 138 * Gets the access time. 139 * 140 * @throws UnsupportedOperationException if the entry hasn't got an access time. 141 * @return the access time 142 * @since 1.23 143 */ 144 public FileTime getAccessTime() { 145 if (hasAccessDate) { 146 return accessDate; 147 } 148 throw new UnsupportedOperationException("The entry doesn't have this timestamp"); 149 } 150 151 /** 152 * Gets the compressed CRC. 153 * 154 * @return the compressed CRC 155 * @deprecated Use {@link #getCompressedCrcValue()} instead. 156 */ 157 @Deprecated 158 int getCompressedCrc() { 159 return (int) compressedCrc; 160 } 161 162 /** 163 * Gets the compressed CRC. 164 * 165 * @return the CRC 166 * @since 1.7 167 */ 168 long getCompressedCrcValue() { 169 return compressedCrc; 170 } 171 172 /** 173 * Gets this entry's compressed file size. 174 * 175 * @return This entry's compressed file size. 176 */ 177 long getCompressedSize() { 178 return compressedSize; 179 } 180 181 /** 182 * Gets the (compression) methods to use for entry's content - the default is LZMA2. 183 * 184 * <p> 185 * Currently only {@link SevenZMethod#COPY}, {@link SevenZMethod#LZMA2}, {@link SevenZMethod#BZIP2} and {@link SevenZMethod#DEFLATE} are supported when 186 * writing archives. 187 * </p> 188 * 189 * <p> 190 * The methods will be consulted in iteration order to create the final output. 191 * </p> 192 * 193 * @return the methods to use for the content 194 * @since 1.8 195 */ 196 public Iterable<? extends SevenZMethodConfiguration> getContentMethods() { 197 return contentMethods; 198 } 199 200 /** 201 * Gets the CRC. 202 * 203 * @deprecated use getCrcValue instead. 204 * @return the CRC 205 */ 206 @Deprecated 207 public int getCrc() { 208 return (int) crc; 209 } 210 211 /** 212 * Gets the CRC. 213 * 214 * @return the CRC 215 * @since 1.7 216 */ 217 public long getCrcValue() { 218 return crc; 219 } 220 221 /** 222 * Gets the creation date. This is equivalent to {@link SevenZArchiveEntry#getCreationTime()}, but precision is truncated to milliseconds. 223 * 224 * @throws UnsupportedOperationException if the entry hasn't got a creation date. 225 * @return the new creation date 226 * @see SevenZArchiveEntry#getCreationTime() 227 */ 228 public Date getCreationDate() { 229 return FileTimes.toDate(getCreationTime()); 230 } 231 232 /** 233 * Gets the creation time. 234 * 235 * @throws UnsupportedOperationException if the entry hasn't got a creation time. 236 * @return the creation time 237 * @since 1.23 238 */ 239 public FileTime getCreationTime() { 240 if (hasCreationDate) { 241 return creationDate; 242 } 243 throw new UnsupportedOperationException("The entry doesn't have this timestamp"); 244 } 245 246 /** 247 * Gets whether this entry has got an access date at all. 248 * 249 * @return whether this entry has got an access date at all. 250 */ 251 public boolean getHasAccessDate() { 252 return hasAccessDate; 253 } 254 255 /** 256 * Gets whether this entry has got a CRC. 257 * 258 * <p> 259 * In general entries without streams don't have a CRC either. 260 * </p> 261 * 262 * @return whether this entry has got a CRC. 263 */ 264 public boolean getHasCrc() { 265 return hasCrc; 266 } 267 268 /** 269 * Gets whether this entry has got a creation date at all. 270 * 271 * @return whether the entry has got a creation date 272 */ 273 public boolean getHasCreationDate() { 274 return hasCreationDate; 275 } 276 277 /** 278 * Gets whether this entry has got a last modified date at all. 279 * 280 * @return whether this entry has got a last modified date at all 281 */ 282 public boolean getHasLastModifiedDate() { 283 return hasLastModifiedDate; 284 } 285 286 /** 287 * Gets whether this entry has windows attributes. 288 * 289 * @return whether this entry has windows attributes. 290 */ 291 public boolean getHasWindowsAttributes() { 292 return hasWindowsAttributes; 293 } 294 295 /** 296 * Gets the last modified date. This is equivalent to {@link SevenZArchiveEntry#getLastModifiedTime()}, but precision is truncated to milliseconds. 297 * 298 * @throws UnsupportedOperationException if the entry hasn't got a last modified date. 299 * @return the last modified date 300 * @see SevenZArchiveEntry#getLastModifiedTime() 301 */ 302 @Override 303 public Date getLastModifiedDate() { 304 return FileTimes.toDate(getLastModifiedTime()); 305 } 306 307 /** 308 * Gets the last modified time. 309 * 310 * @throws UnsupportedOperationException if the entry hasn't got a last modified time. 311 * @return the last modified time 312 * @since 1.23 313 */ 314 public FileTime getLastModifiedTime() { 315 if (hasLastModifiedDate) { 316 return lastModifiedDate; 317 } 318 throw new UnsupportedOperationException("The entry doesn't have this timestamp"); 319 } 320 321 /** 322 * Gets this entry's name. 323 * 324 * <p> 325 * This method returns the raw name as it is stored inside of the archive. 326 * </p> 327 * 328 * @return This entry's name. 329 */ 330 @Override 331 public String getName() { 332 return name; 333 } 334 335 /** 336 * Gets this entry's file size. 337 * 338 * @return This entry's file size. 339 */ 340 @Override 341 public long getSize() { 342 return size; 343 } 344 345 /** 346 * Gets the windows attributes. 347 * 348 * @return the windows attributes 349 */ 350 public int getWindowsAttributes() { 351 return windowsAttributes; 352 } 353 354 @Override 355 public int hashCode() { 356 final String n = getName(); 357 return n == null ? 0 : n.hashCode(); 358 } 359 360 /** 361 * Tests whether there is any content associated with this entry. 362 * <p> 363 * Returns true if a content is present. 364 * </p> 365 * 366 * @return whether there is any content associated with this entry. 367 */ 368 public boolean hasStream() { 369 return hasStream; 370 } 371 372 /** 373 * Tests whether this is an "anti-item" used in differential backups, meaning it should delete the same file from a previous backup. 374 * 375 * @return true if it is an anti-item, false otherwise 376 */ 377 public boolean isAntiItem() { 378 return isAntiItem; 379 } 380 381 /** 382 * Tests whether or not this entry represents a directory. 383 * 384 * @return True if this entry is a directory. 385 */ 386 @Override 387 public boolean isDirectory() { 388 return isDirectory; 389 } 390 391 /** 392 * Tests whether there is any content associated with this entry. 393 * <p> 394 * Returns true if a content is absent. 395 * </p> 396 * 397 * @return whether there is any content associated with this entry. 398 * @since 1.28.0 399 */ 400 public boolean isEmptyStream() { 401 return !hasStream; 402 } 403 404 /** 405 * Sets the access date. 406 * 407 * @param accessDate the new access date 408 * @see SevenZArchiveEntry#setAccessTime(FileTime) 409 */ 410 public void setAccessDate(final Date accessDate) { 411 setAccessTime(FileTimes.toFileTime(accessDate)); 412 } 413 414 /** 415 * Sets the access date using NTFS time (100 nanosecond units since 1 January 1601) 416 * 417 * @param ntfsAccessDate the access date 418 */ 419 public void setAccessDate(final long ntfsAccessDate) { 420 this.accessDate = FileTimes.ntfsTimeToFileTime(ntfsAccessDate); 421 } 422 423 /** 424 * Sets the access time. 425 * 426 * @param time the new access time 427 * @since 1.23 428 */ 429 public void setAccessTime(final FileTime time) { 430 hasAccessDate = time != null; 431 if (hasAccessDate) { 432 this.accessDate = time; 433 } 434 } 435 436 /** 437 * Sets whether this is an "anti-item" used in differential backups, meaning it should delete the same file from a previous backup. 438 * 439 * @param isAntiItem true if it is an anti-item, false otherwise 440 */ 441 public void setAntiItem(final boolean isAntiItem) { 442 this.isAntiItem = isAntiItem; 443 } 444 445 /** 446 * Sets the compressed CRC. 447 * 448 * @deprecated use setCompressedCrcValue instead. 449 * @param crc the CRC 450 */ 451 @Deprecated 452 void setCompressedCrc(final int crc) { 453 this.compressedCrc = crc; 454 } 455 456 /** 457 * Sets the compressed CRC. 458 * 459 * @param crc the CRC 460 * @since 1.7 461 */ 462 void setCompressedCrcValue(final long crc) { 463 this.compressedCrc = crc; 464 } 465 466 /** 467 * Sets this entry's compressed file size. 468 * 469 * @param size This entry's new compressed file size. 470 */ 471 void setCompressedSize(final long size) { 472 this.compressedSize = size; 473 } 474 475 /** 476 * Sets the (compression) methods to use for entry's content - the default is LZMA2. 477 * 478 * <p> 479 * Currently only {@link SevenZMethod#COPY}, {@link SevenZMethod#LZMA2}, {@link SevenZMethod#BZIP2} and {@link SevenZMethod#DEFLATE} are supported when 480 * writing archives. 481 * </p> 482 * 483 * <p> 484 * The methods will be consulted in iteration order to create the final output. 485 * </p> 486 * 487 * @param methods the methods to use for the content 488 * @since 1.8 489 */ 490 public void setContentMethods(final Iterable<? extends SevenZMethodConfiguration> methods) { 491 if (methods != null) { 492 final LinkedList<SevenZMethodConfiguration> l = new LinkedList<>(); 493 methods.forEach(l::addLast); 494 contentMethods = Collections.unmodifiableList(l); 495 } else { 496 contentMethods = null; 497 } 498 } 499 500 /** 501 * Sets the (compression) methods to use for entry's content - the default is LZMA2. 502 * 503 * <p> 504 * Currently only {@link SevenZMethod#COPY}, {@link SevenZMethod#LZMA2}, {@link SevenZMethod#BZIP2} and {@link SevenZMethod#DEFLATE} are supported when 505 * writing archives. 506 * </p> 507 * 508 * <p> 509 * The methods will be consulted in iteration order to create the final output. 510 * </p> 511 * 512 * @param methods the methods to use for the content 513 * @since 1.22 514 */ 515 public void setContentMethods(final SevenZMethodConfiguration... methods) { 516 setContentMethods(Arrays.asList(methods)); 517 } 518 519 /** 520 * Sets the CRC. 521 * 522 * @deprecated use setCrcValue instead. 523 * @param crc the CRC 524 */ 525 @Deprecated 526 public void setCrc(final int crc) { 527 this.crc = crc; 528 } 529 530 /** 531 * Sets the CRC. 532 * 533 * @param crc the CRC 534 * @since 1.7 535 */ 536 public void setCrcValue(final long crc) { 537 this.crc = crc; 538 } 539 540 /** 541 * Sets the creation date. 542 * 543 * @param creationDate the new creation date 544 * @see SevenZArchiveEntry#setCreationTime(FileTime) 545 */ 546 public void setCreationDate(final Date creationDate) { 547 setCreationTime(FileTimes.toFileTime(creationDate)); 548 } 549 550 /** 551 * Sets the creation date using NTFS time (100 nanosecond units since 1 January 1601) 552 * 553 * @param ntfsCreationDate the creation date 554 */ 555 public void setCreationDate(final long ntfsCreationDate) { 556 this.creationDate = FileTimes.ntfsTimeToFileTime(ntfsCreationDate); 557 } 558 559 /** 560 * Sets the creation time. 561 * 562 * @param time the new creation time 563 * @since 1.23 564 */ 565 public void setCreationTime(final FileTime time) { 566 hasCreationDate = time != null; 567 if (hasCreationDate) { 568 this.creationDate = time; 569 } 570 } 571 572 /** 573 * Sets whether or not this entry represents a directory. 574 * 575 * @param isDirectory True if this entry is a directory. 576 */ 577 public void setDirectory(final boolean isDirectory) { 578 this.isDirectory = isDirectory; 579 } 580 581 /** 582 * Sets whether this entry has got an access date at all. 583 * 584 * @param hasAcessDate whether this entry has got an access date at all. 585 */ 586 public void setHasAccessDate(final boolean hasAcessDate) { 587 this.hasAccessDate = hasAcessDate; 588 } 589 590 /** 591 * Sets whether this entry has got a CRC. 592 * 593 * @param hasCrc whether this entry has got a CRC. 594 */ 595 public void setHasCrc(final boolean hasCrc) { 596 this.hasCrc = hasCrc; 597 } 598 599 /** 600 * Sets whether this entry has got a creation date at all. 601 * 602 * @param hasCreationDate whether the entry has got a creation date 603 */ 604 public void setHasCreationDate(final boolean hasCreationDate) { 605 this.hasCreationDate = hasCreationDate; 606 } 607 608 /** 609 * Sets whether this entry has got a last modified date at all. 610 * 611 * @param hasLastModifiedDate whether this entry has got a last modified date at all 612 */ 613 public void setHasLastModifiedDate(final boolean hasLastModifiedDate) { 614 this.hasLastModifiedDate = hasLastModifiedDate; 615 } 616 617 /** 618 * Sets whether there is any content associated with this entry. 619 * 620 * @param hasStream whether there is any content associated with this entry. 621 */ 622 public void setHasStream(final boolean hasStream) { 623 this.hasStream = hasStream; 624 } 625 626 /** 627 * Sets whether this entry has windows attributes. 628 * 629 * @param hasWindowsAttributes whether this entry has windows attributes. 630 */ 631 public void setHasWindowsAttributes(final boolean hasWindowsAttributes) { 632 this.hasWindowsAttributes = hasWindowsAttributes; 633 } 634 635 /** 636 * Sets the last modified date. 637 * 638 * @param lastModifiedDate the new last modified date 639 * @see SevenZArchiveEntry#setLastModifiedTime(FileTime) 640 */ 641 public void setLastModifiedDate(final Date lastModifiedDate) { 642 setLastModifiedTime(FileTimes.toFileTime(lastModifiedDate)); 643 } 644 645 /** 646 * Sets the last modified date using NTFS time (100 nanosecond units since 1 January 1601) 647 * 648 * @param ntfsLastModifiedDate the last modified date 649 */ 650 public void setLastModifiedDate(final long ntfsLastModifiedDate) { 651 this.lastModifiedDate = FileTimes.ntfsTimeToFileTime(ntfsLastModifiedDate); 652 } 653 654 /** 655 * Sets the last modified time. 656 * 657 * @param time the new last modified time 658 * @since 1.23 659 */ 660 public void setLastModifiedTime(final FileTime time) { 661 hasLastModifiedDate = time != null; 662 if (hasLastModifiedDate) { 663 this.lastModifiedDate = time; 664 } 665 } 666 667 /** 668 * Sets this entry's name. 669 * 670 * @param name This entry's new name. 671 */ 672 public void setName(final String name) { 673 this.name = name; 674 } 675 676 /** 677 * Sets this entry's file size. 678 * 679 * @param size This entry's new file size. 680 */ 681 public void setSize(final long size) { 682 this.size = size; 683 } 684 685 /** 686 * Sets the windows attributes. 687 * 688 * @param windowsAttributes the windows attributes 689 */ 690 public void setWindowsAttributes(final int windowsAttributes) { 691 this.windowsAttributes = windowsAttributes; 692 } 693}