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