View Javadoc
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  package org.apache.commons.compress.archivers.sevenz;
18  
19  import java.nio.file.attribute.FileTime;
20  import java.util.Arrays;
21  import java.util.Collections;
22  import java.util.Date;
23  import java.util.Iterator;
24  import java.util.LinkedList;
25  import java.util.Objects;
26  
27  import org.apache.commons.compress.archivers.ArchiveEntry;
28  import org.apache.commons.io.file.attribute.FileTimes;
29  
30  /**
31   * An entry in a 7z archive.
32   *
33   * @NotThreadSafe
34   * @since 1.6
35   */
36  public class SevenZArchiveEntry implements ArchiveEntry {
37  
38      static final SevenZArchiveEntry[] EMPTY_SEVEN_Z_ARCHIVE_ENTRY_ARRAY = {};
39  
40      /**
41       * Converts Java time to NTFS time.
42       *
43       * @param date the Java time
44       * @return the NTFS time
45       * @deprecated Use {@link FileTimes#toNtfsTime(Date)} instead.
46       * @see FileTimes#toNtfsTime(Date)
47       */
48      @Deprecated
49      public static long javaTimeToNtfsTime(final Date date) {
50          return FileTimes.toNtfsTime(date);
51      }
52  
53      /**
54       * Converts NTFS time (100 nanosecond units since 1 January 1601) to Java time.
55       *
56       * @param ntfsTime the NTFS time in 100 nanosecond units
57       * @return the Java time
58       * @deprecated Use {@link FileTimes#ntfsTimeToDate(long)} instead.
59       * @see FileTimes#ntfsTimeToDate(long)
60       */
61      @Deprecated
62      public static Date ntfsTimeToJavaTime(final long ntfsTime) {
63          return FileTimes.ntfsTimeToDate(ntfsTime);
64      }
65  
66      private String name;
67      private boolean hasStream;
68      private boolean isDirectory;
69      private boolean isAntiItem;
70      private boolean hasCreationDate;
71      private boolean hasLastModifiedDate;
72      private boolean hasAccessDate;
73      private FileTime creationDate;
74      private FileTime lastModifiedDate;
75      private FileTime accessDate;
76      private boolean hasWindowsAttributes;
77      private int windowsAttributes;
78      private boolean hasCrc;
79      private long crc, compressedCrc;
80      private long size, compressedSize;
81      private Iterable<? extends SevenZMethodConfiguration> contentMethods;
82  
83      /**
84       * Constructs a new instance.
85       */
86      public SevenZArchiveEntry() {
87      }
88  
89      @Override
90      public boolean equals(final Object obj) {
91          if (this == obj) {
92              return true;
93          }
94          if (obj == null || getClass() != obj.getClass()) {
95              return false;
96          }
97          final SevenZArchiveEntry other = (SevenZArchiveEntry) obj;
98          return Objects.equals(name, other.name) && hasStream == other.hasStream && isDirectory == other.isDirectory && isAntiItem == other.isAntiItem
99                  && hasCreationDate == other.hasCreationDate && hasLastModifiedDate == other.hasLastModifiedDate && hasAccessDate == other.hasAccessDate
100                 && Objects.equals(creationDate, other.creationDate) && Objects.equals(lastModifiedDate, other.lastModifiedDate)
101                 && Objects.equals(accessDate, other.accessDate) && hasWindowsAttributes == other.hasWindowsAttributes
102                 && windowsAttributes == other.windowsAttributes && hasCrc == other.hasCrc && crc == other.crc && compressedCrc == other.compressedCrc
103                 && size == other.size && compressedSize == other.compressedSize && equalSevenZMethods(contentMethods, other.contentMethods);
104     }
105 
106     private boolean equalSevenZMethods(final Iterable<? extends SevenZMethodConfiguration> c1, final Iterable<? extends SevenZMethodConfiguration> c2) {
107         if (c1 == null) {
108             return c2 == null;
109         }
110         if (c2 == null) {
111             return false;
112         }
113         final Iterator<? extends SevenZMethodConfiguration> i2 = c2.iterator();
114         for (final SevenZMethodConfiguration element : c1) {
115             if (!i2.hasNext()) {
116                 return false;
117             }
118             if (!element.equals(i2.next())) {
119                 return false;
120             }
121         }
122         return !i2.hasNext();
123     }
124 
125     /**
126      * Gets the access date. This is equivalent to {@link SevenZArchiveEntry#getAccessTime()}, but precision is truncated to milliseconds.
127      *
128      * @throws UnsupportedOperationException if the entry hasn't got an access date.
129      * @return the access date
130      * @see SevenZArchiveEntry#getAccessTime()
131      */
132     public Date getAccessDate() {
133         return FileTimes.toDate(getAccessTime());
134     }
135 
136     /**
137      * Gets the access time.
138      *
139      * @throws UnsupportedOperationException if the entry hasn't got an access time.
140      * @return the access time
141      * @since 1.23
142      */
143     public FileTime getAccessTime() {
144         if (hasAccessDate) {
145             return accessDate;
146         }
147         throw new UnsupportedOperationException("The entry doesn't have this timestamp");
148     }
149 
150     /**
151      * Gets the compressed CRC.
152      *
153      * @return the compressed CRC
154      * @deprecated Use {@link #getCompressedCrcValue()} instead.
155      */
156     @Deprecated
157     int getCompressedCrc() {
158         return (int) compressedCrc;
159     }
160 
161     /**
162      * Gets the compressed CRC.
163      *
164      * @since 1.7
165      * @return the CRC
166      */
167     long getCompressedCrcValue() {
168         return compressedCrc;
169     }
170 
171     /**
172      * Gets this entry's compressed file size.
173      *
174      * @return This entry's compressed file size.
175      */
176     long getCompressedSize() {
177         return compressedSize;
178     }
179 
180     /**
181      * Gets the (compression) methods to use for entry's content - the default is LZMA2.
182      *
183      * <p>
184      * Currently only {@link SevenZMethod#COPY}, {@link SevenZMethod#LZMA2}, {@link SevenZMethod#BZIP2} and {@link SevenZMethod#DEFLATE} are supported when
185      * writing archives.
186      * </p>
187      *
188      * <p>
189      * The methods will be consulted in iteration order to create the final output.
190      * </p>
191      *
192      * @since 1.8
193      * @return the methods to use for the content
194      */
195     public Iterable<? extends SevenZMethodConfiguration> getContentMethods() {
196         return contentMethods;
197     }
198 
199     /**
200      * Gets the CRC.
201      *
202      * @deprecated use getCrcValue instead.
203      * @return the CRC
204      */
205     @Deprecated
206     public int getCrc() {
207         return (int) crc;
208     }
209 
210     /**
211      * Gets the CRC.
212      *
213      * @since 1.7
214      * @return the CRC
215      */
216     public long getCrcValue() {
217         return crc;
218     }
219 
220     /**
221      * Gets the creation date. This is equivalent to {@link SevenZArchiveEntry#getCreationTime()}, but precision is truncated to milliseconds.
222      *
223      * @throws UnsupportedOperationException if the entry hasn't got a creation date.
224      * @return the new creation date
225      * @see SevenZArchiveEntry#getCreationTime()
226      */
227     public Date getCreationDate() {
228         return FileTimes.toDate(getCreationTime());
229     }
230 
231     /**
232      * Gets the creation time.
233      *
234      * @throws UnsupportedOperationException if the entry hasn't got a creation time.
235      * @return the creation time
236      * @since 1.23
237      */
238     public FileTime getCreationTime() {
239         if (hasCreationDate) {
240             return creationDate;
241         }
242         throw new UnsupportedOperationException("The entry doesn't have this timestamp");
243     }
244 
245     /**
246      * Gets whether this entry has got an access date at all.
247      *
248      * @return whether this entry has got an access date at all.
249      */
250     public boolean getHasAccessDate() {
251         return hasAccessDate;
252     }
253 
254     /**
255      * Gets whether this entry has got a crc.
256      *
257      * <p>
258      * In general entries without streams don't have a CRC either.
259      * </p>
260      *
261      * @return whether this entry has got a crc.
262      */
263     public boolean getHasCrc() {
264         return hasCrc;
265     }
266 
267     /**
268      * Gets whether this entry has got a creation date at all.
269      *
270      * @return whether the entry has got a creation date
271      */
272     public boolean getHasCreationDate() {
273         return hasCreationDate;
274     }
275 
276     /**
277      * Gets whether this entry has got a last modified date at all.
278      *
279      * @return whether this entry has got a last modified date at all
280      */
281     public boolean getHasLastModifiedDate() {
282         return hasLastModifiedDate;
283     }
284 
285     /**
286      * Gets whether this entry has windows attributes.
287      *
288      * @return whether this entry has windows attributes.
289      */
290     public boolean getHasWindowsAttributes() {
291         return hasWindowsAttributes;
292     }
293 
294     /**
295      * Gets the last modified date. This is equivalent to {@link SevenZArchiveEntry#getLastModifiedTime()}, but precision is truncated to milliseconds.
296      *
297      * @throws UnsupportedOperationException if the entry hasn't got a last modified date.
298      * @return the last modified date
299      * @see SevenZArchiveEntry#getLastModifiedTime()
300      */
301     @Override
302     public Date getLastModifiedDate() {
303         return FileTimes.toDate(getLastModifiedTime());
304     }
305 
306     /**
307      * Gets the last modified time.
308      *
309      * @throws UnsupportedOperationException if the entry hasn't got a last modified time.
310      * @return the last modified time
311      * @since 1.23
312      */
313     public FileTime getLastModifiedTime() {
314         if (hasLastModifiedDate) {
315             return lastModifiedDate;
316         }
317         throw new UnsupportedOperationException("The entry doesn't have this timestamp");
318     }
319 
320     /**
321      * Gets this entry's name.
322      *
323      * <p>
324      * This method returns the raw name as it is stored inside of the archive.
325      * </p>
326      *
327      * @return This entry's name.
328      */
329     @Override
330     public String getName() {
331         return name;
332     }
333 
334     /**
335      * Gets this entry's file size.
336      *
337      * @return This entry's file size.
338      */
339     @Override
340     public long getSize() {
341         return size;
342     }
343 
344     /**
345      * Gets the windows attributes.
346      *
347      * @return the windows attributes
348      */
349     public int getWindowsAttributes() {
350         return windowsAttributes;
351     }
352 
353     @Override
354     public int hashCode() {
355         final String n = getName();
356         return n == null ? 0 : n.hashCode();
357     }
358 
359     /**
360      * Tests whether there is any content associated with this entry.
361      *
362      * @return whether there is any content associated with this entry.
363      */
364     public boolean hasStream() {
365         return hasStream;
366     }
367 
368     /**
369      * Tests whether this is an "anti-item" used in differential backups, meaning it should delete the same file from a previous backup.
370      *
371      * @return true if it is an anti-item, false otherwise
372      */
373     public boolean isAntiItem() {
374         return isAntiItem;
375     }
376 
377     /**
378      * Tests whether or not this entry represents a directory.
379      *
380      * @return True if this entry is a directory.
381      */
382     @Override
383     public boolean isDirectory() {
384         return isDirectory;
385     }
386 
387     /**
388      * Sets the access date.
389      *
390      * @param accessDate the new access date
391      * @see SevenZArchiveEntry#setAccessTime(FileTime)
392      */
393     public void setAccessDate(final Date accessDate) {
394         setAccessTime(FileTimes.toFileTime(accessDate));
395     }
396 
397     /**
398      * Sets the access date using NTFS time (100 nanosecond units since 1 January 1601)
399      *
400      * @param ntfsAccessDate the access date
401      */
402     public void setAccessDate(final long ntfsAccessDate) {
403         this.accessDate = FileTimes.ntfsTimeToFileTime(ntfsAccessDate);
404     }
405 
406     /**
407      * Sets the access time.
408      *
409      * @param time the new access time
410      * @since 1.23
411      */
412     public void setAccessTime(final FileTime time) {
413         hasAccessDate = time != null;
414         if (hasAccessDate) {
415             this.accessDate = time;
416         }
417     }
418 
419     /**
420      * Sets whether this is an "anti-item" used in differential backups, meaning it should delete the same file from a previous backup.
421      *
422      * @param isAntiItem true if it is an anti-item, false otherwise
423      */
424     public void setAntiItem(final boolean isAntiItem) {
425         this.isAntiItem = isAntiItem;
426     }
427 
428     /**
429      * Sets the compressed CRC.
430      *
431      * @deprecated use setCompressedCrcValue instead.
432      * @param crc the CRC
433      */
434     @Deprecated
435     void setCompressedCrc(final int crc) {
436         this.compressedCrc = crc;
437     }
438 
439     /**
440      * Sets the compressed CRC.
441      *
442      * @since 1.7
443      * @param crc the CRC
444      */
445     void setCompressedCrcValue(final long crc) {
446         this.compressedCrc = crc;
447     }
448 
449     /**
450      * Sets this entry's compressed file size.
451      *
452      * @param size This entry's new compressed file size.
453      */
454     void setCompressedSize(final long size) {
455         this.compressedSize = size;
456     }
457 
458     /**
459      * Sets the (compression) methods to use for entry's content - the default is LZMA2.
460      *
461      * <p>
462      * Currently only {@link SevenZMethod#COPY}, {@link SevenZMethod#LZMA2}, {@link SevenZMethod#BZIP2} and {@link SevenZMethod#DEFLATE} are supported when
463      * writing archives.
464      * </p>
465      *
466      * <p>
467      * The methods will be consulted in iteration order to create the final output.
468      * </p>
469      *
470      * @param methods the methods to use for the content
471      * @since 1.8
472      */
473     public void setContentMethods(final Iterable<? extends SevenZMethodConfiguration> methods) {
474         if (methods != null) {
475             final LinkedList<SevenZMethodConfiguration> l = new LinkedList<>();
476             methods.forEach(l::addLast);
477             contentMethods = Collections.unmodifiableList(l);
478         } else {
479             contentMethods = null;
480         }
481     }
482 
483     /**
484      * Sets the (compression) methods to use for entry's content - the default is LZMA2.
485      *
486      * <p>
487      * Currently only {@link SevenZMethod#COPY}, {@link SevenZMethod#LZMA2}, {@link SevenZMethod#BZIP2} and {@link SevenZMethod#DEFLATE} are supported when
488      * writing archives.
489      * </p>
490      *
491      * <p>
492      * The methods will be consulted in iteration order to create the final output.
493      * </p>
494      *
495      * @param methods the methods to use for the content
496      * @since 1.22
497      */
498     public void setContentMethods(final SevenZMethodConfiguration... methods) {
499         setContentMethods(Arrays.asList(methods));
500     }
501 
502     /**
503      * Sets the CRC.
504      *
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      *
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(FileTimes.toFileTime(creationDate));
531     }
532 
533     /**
534      * Sets the creation date using NTFS time (100 nanosecond units since 1 January 1601)
535      *
536      * @param ntfsCreationDate the creation date
537      */
538     public void setCreationDate(final long ntfsCreationDate) {
539         this.creationDate = FileTimes.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      *
567      * @param hasAcessDate whether this entry has got an access date at all.
568      */
569     public void setHasAccessDate(final boolean hasAcessDate) {
570         this.hasAccessDate = hasAcessDate;
571     }
572 
573     /**
574      * Sets whether this entry has got a crc.
575      *
576      * @param hasCrc whether this entry has got a crc.
577      */
578     public void setHasCrc(final boolean hasCrc) {
579         this.hasCrc = hasCrc;
580     }
581 
582     /**
583      * Sets whether this entry has got a creation date at all.
584      *
585      * @param hasCreationDate whether the entry has got a creation date
586      */
587     public void setHasCreationDate(final boolean hasCreationDate) {
588         this.hasCreationDate = hasCreationDate;
589     }
590 
591     /**
592      * Sets whether this entry has got a last modified date at all.
593      *
594      * @param hasLastModifiedDate whether this entry has got a last modified date at all
595      */
596     public void setHasLastModifiedDate(final boolean hasLastModifiedDate) {
597         this.hasLastModifiedDate = hasLastModifiedDate;
598     }
599 
600     /**
601      * Sets whether there is any content associated with this entry.
602      *
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      *
612      * @param hasWindowsAttributes whether this entry has windows attributes.
613      */
614     public void setHasWindowsAttributes(final boolean hasWindowsAttributes) {
615         this.hasWindowsAttributes = hasWindowsAttributes;
616     }
617 
618     /**
619      * Sets the last modified date.
620      *
621      * @param lastModifiedDate the new last modified date
622      * @see SevenZArchiveEntry#setLastModifiedTime(FileTime)
623      */
624     public void setLastModifiedDate(final Date lastModifiedDate) {
625         setLastModifiedTime(FileTimes.toFileTime(lastModifiedDate));
626     }
627 
628     /**
629      * Sets the last modified date using NTFS time (100 nanosecond units since 1 January 1601)
630      *
631      * @param ntfsLastModifiedDate the last modified date
632      */
633     public void setLastModifiedDate(final long ntfsLastModifiedDate) {
634         this.lastModifiedDate = FileTimes.ntfsTimeToFileTime(ntfsLastModifiedDate);
635     }
636 
637     /**
638      * Sets the last modified time.
639      *
640      * @param time the new last modified time
641      * @since 1.23
642      */
643     public void setLastModifiedTime(final FileTime time) {
644         hasLastModifiedDate = time != null;
645         if (hasLastModifiedDate) {
646             this.lastModifiedDate = time;
647         }
648     }
649 
650     /**
651      * Sets this entry's name.
652      *
653      * @param name This entry's new name.
654      */
655     public void setName(final String name) {
656         this.name = name;
657     }
658 
659     /**
660      * Sets this entry's file size.
661      *
662      * @param size This entry's new file size.
663      */
664     public void setSize(final long size) {
665         this.size = size;
666     }
667 
668     /**
669      * Sets the windows attributes.
670      *
671      * @param windowsAttributes the windows attributes
672      */
673     public void setWindowsAttributes(final int windowsAttributes) {
674         this.windowsAttributes = windowsAttributes;
675     }
676 }