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