1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 package org.apache.commons.compress.archivers.sevenz; 19 20 import java.util.Calendar; 21 import java.util.Collections; 22 import java.util.Date; 23 import java.util.LinkedList; 24 import java.util.TimeZone; 25 26 import org.apache.commons.compress.archivers.ArchiveEntry; 27 28 /** 29 * An entry in a 7z archive. 30 * 31 * @NotThreadSafe 32 * @since 1.6 33 */ 34 public class SevenZArchiveEntry implements ArchiveEntry { 35 private String name; 36 private boolean hasStream; 37 private boolean isDirectory; 38 private boolean isAntiItem; 39 private boolean hasCreationDate; 40 private boolean hasLastModifiedDate; 41 private boolean hasAccessDate; 42 private long creationDate; 43 private long lastModifiedDate; 44 private long accessDate; 45 private boolean hasWindowsAttributes; 46 private int windowsAttributes; 47 private boolean hasCrc; 48 private long crc, compressedCrc; 49 private long size, compressedSize; 50 private Iterable<? extends SevenZMethodConfiguration> contentMethods; 51 SevenZArchiveEntry()52 public SevenZArchiveEntry() { 53 } 54 55 /** 56 * Get this entry's name. 57 * 58 * <p>This method returns the raw name as it is stored inside of the archive.</p> 59 * 60 * @return This entry's name. 61 */ 62 @Override getName()63 public String getName() { 64 return name; 65 } 66 67 /** 68 * Set this entry's name. 69 * 70 * @param name This entry's new name. 71 */ setName(final String name)72 public void setName(final String name) { 73 this.name = name; 74 } 75 76 /** 77 * Whether there is any content associated with this entry. 78 * @return whether there is any content associated with this entry. 79 */ hasStream()80 public boolean hasStream() { 81 return hasStream; 82 } 83 84 /** 85 * Sets whether there is any content associated with this entry. 86 * @param hasStream whether there is any content associated with this entry. 87 */ setHasStream(final boolean hasStream)88 public void setHasStream(final boolean hasStream) { 89 this.hasStream = hasStream; 90 } 91 92 /** 93 * Return whether or not this entry represents a directory. 94 * 95 * @return True if this entry is a directory. 96 */ 97 @Override isDirectory()98 public boolean isDirectory() { 99 return isDirectory; 100 } 101 102 /** 103 * Sets whether or not this entry represents a directory. 104 * 105 * @param isDirectory True if this entry is a directory. 106 */ setDirectory(final boolean isDirectory)107 public void setDirectory(final boolean isDirectory) { 108 this.isDirectory = isDirectory; 109 } 110 111 /** 112 * Indicates whether this is an "anti-item" used in differential backups, 113 * meaning it should delete the same file from a previous backup. 114 * @return true if it is an anti-item, false otherwise 115 */ isAntiItem()116 public boolean isAntiItem() { 117 return isAntiItem; 118 } 119 120 /** 121 * Sets whether this is an "anti-item" used in differential backups, 122 * meaning it should delete the same file from a previous backup. 123 * @param isAntiItem true if it is an anti-item, false otherwise 124 */ setAntiItem(final boolean isAntiItem)125 public void setAntiItem(final boolean isAntiItem) { 126 this.isAntiItem = isAntiItem; 127 } 128 129 /** 130 * Returns whether this entry has got a creation date at all. 131 * @return whether the entry has got a creation date 132 */ getHasCreationDate()133 public boolean getHasCreationDate() { 134 return hasCreationDate; 135 } 136 137 /** 138 * Sets whether this entry has got a creation date at all. 139 * @param hasCreationDate whether the entry has got a creation date 140 */ setHasCreationDate(final boolean hasCreationDate)141 public void setHasCreationDate(final boolean hasCreationDate) { 142 this.hasCreationDate = hasCreationDate; 143 } 144 145 /** 146 * Gets the creation date. 147 * @throws UnsupportedOperationException if the entry hasn't got a 148 * creation date. 149 * @return the creation date 150 */ getCreationDate()151 public Date getCreationDate() { 152 if (hasCreationDate) { 153 return ntfsTimeToJavaTime(creationDate); 154 } 155 throw new UnsupportedOperationException( 156 "The entry doesn't have this timestamp"); 157 } 158 159 /** 160 * Sets the creation date using NTFS time (100 nanosecond units 161 * since 1 January 1601) 162 * @param ntfsCreationDate the creation date 163 */ setCreationDate(final long ntfsCreationDate)164 public void setCreationDate(final long ntfsCreationDate) { 165 this.creationDate = ntfsCreationDate; 166 } 167 168 /** 169 * Sets the creation date, 170 * @param creationDate the creation date 171 */ setCreationDate(final Date creationDate)172 public void setCreationDate(final Date creationDate) { 173 hasCreationDate = creationDate != null; 174 if (hasCreationDate) { 175 this.creationDate = javaTimeToNtfsTime(creationDate); 176 } 177 } 178 179 /** 180 * Returns whether this entry has got a last modified date at all. 181 * @return whether this entry has got a last modified date at all 182 */ getHasLastModifiedDate()183 public boolean getHasLastModifiedDate() { 184 return hasLastModifiedDate; 185 } 186 187 /** 188 * Sets whether this entry has got a last modified date at all. 189 * @param hasLastModifiedDate whether this entry has got a last 190 * modified date at all 191 */ setHasLastModifiedDate(final boolean hasLastModifiedDate)192 public void setHasLastModifiedDate(final boolean hasLastModifiedDate) { 193 this.hasLastModifiedDate = hasLastModifiedDate; 194 } 195 196 /** 197 * Gets the last modified date. 198 * @throws UnsupportedOperationException if the entry hasn't got a 199 * last modified date. 200 * @return the last modified date 201 */ 202 @Override getLastModifiedDate()203 public Date getLastModifiedDate() { 204 if (hasLastModifiedDate) { 205 return ntfsTimeToJavaTime(lastModifiedDate); 206 } 207 throw new UnsupportedOperationException( 208 "The entry doesn't have this timestamp"); 209 } 210 211 /** 212 * Sets the last modified date using NTFS time (100 nanosecond 213 * units since 1 January 1601) 214 * @param ntfsLastModifiedDate the last modified date 215 */ setLastModifiedDate(final long ntfsLastModifiedDate)216 public void setLastModifiedDate(final long ntfsLastModifiedDate) { 217 this.lastModifiedDate = ntfsLastModifiedDate; 218 } 219 220 /** 221 * Sets the last modified date, 222 * @param lastModifiedDate the last modified date 223 */ setLastModifiedDate(final Date lastModifiedDate)224 public void setLastModifiedDate(final Date lastModifiedDate) { 225 hasLastModifiedDate = lastModifiedDate != null; 226 if (hasLastModifiedDate) { 227 this.lastModifiedDate = javaTimeToNtfsTime(lastModifiedDate); 228 } 229 } 230 231 /** 232 * Returns whether this entry has got an access date at all. 233 * @return whether this entry has got an access date at all. 234 */ getHasAccessDate()235 public boolean getHasAccessDate() { 236 return hasAccessDate; 237 } 238 239 /** 240 * Sets whether this entry has got an access date at all. 241 * @param hasAcessDate whether this entry has got an access date at all. 242 */ setHasAccessDate(final boolean hasAcessDate)243 public void setHasAccessDate(final boolean hasAcessDate) { 244 this.hasAccessDate = hasAcessDate; 245 } 246 247 /** 248 * Gets the access date. 249 * @throws UnsupportedOperationException if the entry hasn't got a 250 * access date. 251 * @return the access date 252 */ getAccessDate()253 public Date getAccessDate() { 254 if (hasAccessDate) { 255 return ntfsTimeToJavaTime(accessDate); 256 } 257 throw new UnsupportedOperationException( 258 "The entry doesn't have this timestamp"); 259 } 260 261 /** 262 * Sets the access date using NTFS time (100 nanosecond units 263 * since 1 January 1601) 264 * @param ntfsAccessDate the access date 265 */ setAccessDate(final long ntfsAccessDate)266 public void setAccessDate(final long ntfsAccessDate) { 267 this.accessDate = ntfsAccessDate; 268 } 269 270 /** 271 * Sets the access date, 272 * @param accessDate the access date 273 */ setAccessDate(final Date accessDate)274 public void setAccessDate(final Date accessDate) { 275 hasAccessDate = accessDate != null; 276 if (hasAccessDate) { 277 this.accessDate = javaTimeToNtfsTime(accessDate); 278 } 279 } 280 281 /** 282 * Returns whether this entry has windows attributes. 283 * @return whether this entry has windows attributes. 284 */ getHasWindowsAttributes()285 public boolean getHasWindowsAttributes() { 286 return hasWindowsAttributes; 287 } 288 289 /** 290 * Sets whether this entry has windows attributes. 291 * @param hasWindowsAttributes whether this entry has windows attributes. 292 */ setHasWindowsAttributes(final boolean hasWindowsAttributes)293 public void setHasWindowsAttributes(final boolean hasWindowsAttributes) { 294 this.hasWindowsAttributes = hasWindowsAttributes; 295 } 296 297 /** 298 * Gets the windows attributes. 299 * @return the windows attributes 300 */ getWindowsAttributes()301 public int getWindowsAttributes() { 302 return windowsAttributes; 303 } 304 305 /** 306 * Sets the windows attributes. 307 * @param windowsAttributes the windows attributes 308 */ setWindowsAttributes(final int windowsAttributes)309 public void setWindowsAttributes(final int windowsAttributes) { 310 this.windowsAttributes = windowsAttributes; 311 } 312 313 /** 314 * Returns whether this entry has got a crc. 315 * 316 * <p>In general entries without streams don't have a CRC either.</p> 317 * @return whether this entry has got a crc. 318 */ getHasCrc()319 public boolean getHasCrc() { 320 return hasCrc; 321 } 322 323 /** 324 * Sets whether this entry has got a crc. 325 * @param hasCrc whether this entry has got a crc. 326 */ setHasCrc(final boolean hasCrc)327 public void setHasCrc(final boolean hasCrc) { 328 this.hasCrc = hasCrc; 329 } 330 331 /** 332 * Gets the CRC. 333 * @deprecated use getCrcValue instead. 334 * @return the CRC 335 */ 336 @Deprecated getCrc()337 public int getCrc() { 338 return (int) crc; 339 } 340 341 /** 342 * Sets the CRC. 343 * @deprecated use setCrcValue instead. 344 * @param crc the CRC 345 */ 346 @Deprecated setCrc(final int crc)347 public void setCrc(final int crc) { 348 this.crc = crc; 349 } 350 351 /** 352 * Gets the CRC. 353 * @since Compress 1.7 354 * @return the CRC 355 */ getCrcValue()356 public long getCrcValue() { 357 return crc; 358 } 359 360 /** 361 * Sets the CRC. 362 * @since Compress 1.7 363 * @param crc the CRC 364 */ setCrcValue(final long crc)365 public void setCrcValue(final long crc) { 366 this.crc = crc; 367 } 368 369 /** 370 * Gets the compressed CRC. 371 * @deprecated use getCompressedCrcValue instead. 372 * @return the compressed CRC 373 */ 374 @Deprecated getCompressedCrc()375 int getCompressedCrc() { 376 return (int) compressedCrc; 377 } 378 379 /** 380 * Sets the compressed CRC. 381 * @deprecated use setCompressedCrcValue instead. 382 * @param crc the CRC 383 */ 384 @Deprecated setCompressedCrc(final int crc)385 void setCompressedCrc(final int crc) { 386 this.compressedCrc = crc; 387 } 388 389 /** 390 * Gets the compressed CRC. 391 * @since Compress 1.7 392 * @return the CRC 393 */ getCompressedCrcValue()394 long getCompressedCrcValue() { 395 return compressedCrc; 396 } 397 398 /** 399 * Sets the compressed CRC. 400 * @since Compress 1.7 401 * @param crc the CRC 402 */ setCompressedCrcValue(final long crc)403 void setCompressedCrcValue(final long crc) { 404 this.compressedCrc = crc; 405 } 406 407 /** 408 * Get this entry's file size. 409 * 410 * @return This entry's file size. 411 */ 412 @Override getSize()413 public long getSize() { 414 return size; 415 } 416 417 /** 418 * Set this entry's file size. 419 * 420 * @param size This entry's new file size. 421 */ setSize(final long size)422 public void setSize(final long size) { 423 this.size = size; 424 } 425 426 /** 427 * Get this entry's compressed file size. 428 * 429 * @return This entry's compressed file size. 430 */ getCompressedSize()431 long getCompressedSize() { 432 return compressedSize; 433 } 434 435 /** 436 * Set this entry's compressed file size. 437 * 438 * @param size This entry's new compressed file size. 439 */ setCompressedSize(final long size)440 void setCompressedSize(final long size) { 441 this.compressedSize = size; 442 } 443 444 /** 445 * Sets the (compression) methods to use for entry's content - the 446 * default is LZMA2. 447 * 448 * <p>Currently only {@link SevenZMethod#COPY}, {@link 449 * SevenZMethod#LZMA2}, {@link SevenZMethod#BZIP2} and {@link 450 * SevenZMethod#DEFLATE} are supported when writing archives.</p> 451 * 452 * <p>The methods will be consulted in iteration order to create 453 * the final output.</p> 454 * 455 * @param methods the methods to use for the content 456 * @since 1.8 457 */ setContentMethods(final Iterable<? extends SevenZMethodConfiguration> methods)458 public void setContentMethods(final Iterable<? extends SevenZMethodConfiguration> methods) { 459 if (methods != null) { 460 final LinkedList<SevenZMethodConfiguration> l = new LinkedList<>(); 461 for (final SevenZMethodConfiguration m : methods) { 462 l.addLast(m); 463 } 464 contentMethods = Collections.unmodifiableList(l); 465 } else { 466 contentMethods = null; 467 } 468 } 469 470 /** 471 * Gets the (compression) methods to use for entry's content - the 472 * default is LZMA2. 473 * 474 * <p>Currently only {@link SevenZMethod#COPY}, {@link 475 * SevenZMethod#LZMA2}, {@link SevenZMethod#BZIP2} and {@link 476 * SevenZMethod#DEFLATE} are supported when writing archives.</p> 477 * 478 * <p>The methods will be consulted in iteration order to create 479 * the final output.</p> 480 * 481 * @since 1.8 482 * @return the methods to use for the content 483 */ getContentMethods()484 public Iterable<? extends SevenZMethodConfiguration> getContentMethods() { 485 return contentMethods; 486 } 487 488 /** 489 * Converts NTFS time (100 nanosecond units since 1 January 1601) 490 * to Java time. 491 * @param ntfsTime the NTFS time in 100 nanosecond units 492 * @return the Java time 493 */ ntfsTimeToJavaTime(final long ntfsTime)494 public static Date ntfsTimeToJavaTime(final long ntfsTime) { 495 final Calendar ntfsEpoch = Calendar.getInstance(); 496 ntfsEpoch.setTimeZone(TimeZone.getTimeZone("GMT+0")); 497 ntfsEpoch.set(1601, 0, 1, 0, 0, 0); 498 ntfsEpoch.set(Calendar.MILLISECOND, 0); 499 final long realTime = ntfsEpoch.getTimeInMillis() + (ntfsTime / (10*1000)); 500 return new Date(realTime); 501 } 502 503 /** 504 * Converts Java time to NTFS time. 505 * @param date the Java time 506 * @return the NTFS time 507 */ javaTimeToNtfsTime(final Date date)508 public static long javaTimeToNtfsTime(final Date date) { 509 final Calendar ntfsEpoch = Calendar.getInstance(); 510 ntfsEpoch.setTimeZone(TimeZone.getTimeZone("GMT+0")); 511 ntfsEpoch.set(1601, 0, 1, 0, 0, 0); 512 ntfsEpoch.set(Calendar.MILLISECOND, 0); 513 return ((date.getTime() - ntfsEpoch.getTimeInMillis())* 1000 * 10); 514 } 515 } 516