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