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.arj;
018
019import java.io.File;
020import java.util.Date;
021
022import org.apache.commons.compress.archivers.ArchiveEntry;
023import org.apache.commons.compress.archivers.zip.ZipUtil;
024
025/**
026 * An entry in an ARJ archive.
027 *
028 * @NotThreadSafe
029 * @since 1.6
030 */
031public class ArjArchiveEntry implements ArchiveEntry {
032    /**
033     * The known values for HostOs.
034     */
035    public static class HostOs {
036        public static final int DOS = 0;
037        public static final int PRIMOS = 1;
038        public static final int UNIX = 2;
039        public static final int AMIGA = 3;
040        public static final int MAC_OS = 4;
041        public static final int OS_2 = 5;
042        public static final int APPLE_GS = 6;
043        public static final int ATARI_ST = 7;
044        public static final int NEXT = 8;
045        public static final int VAX_VMS = 9;
046        public static final int WIN95 = 10;
047        public static final int WIN32 = 11;
048    }
049
050    private final LocalFileHeader localFileHeader;
051
052    public ArjArchiveEntry() {
053        localFileHeader = new LocalFileHeader();
054    }
055
056    ArjArchiveEntry(final LocalFileHeader localFileHeader) {
057        this.localFileHeader = localFileHeader;
058    }
059
060    @Override
061    public boolean equals(final Object obj) {
062        if (this == obj) {
063            return true;
064        }
065        if (obj == null || getClass() != obj.getClass()) {
066            return false;
067        }
068        final ArjArchiveEntry other = (ArjArchiveEntry) obj;
069        return localFileHeader.equals(other.localFileHeader);
070    }
071
072    /**
073     * The operating system the archive has been created on.
074     * @see HostOs
075     * @return the host OS code
076     */
077    public int getHostOs() {
078        return localFileHeader.hostOS;
079    }
080
081    /**
082     * The last modified date of the entry.
083     *
084     * <p>Note the interpretation of time is different depending on
085     * the HostOS that has created the archive.  While an OS that is
086     * {@link #isHostOsUnix considered to be Unix} stores time in a
087     * time zone independent manner, other platforms only use the local
088     * time.  I.e. if an archive has been created at midnight UTC on a
089     * machine in time zone UTC this method will return midnight
090     * regardless of time zone if the archive has been created on a
091     * non-Unix system and a time taking the current time zone into
092     * account if the archive has been created on Unix.</p>
093     *
094     * @return the last modified date
095     */
096    @Override
097    public Date getLastModifiedDate() {
098        final long ts = isHostOsUnix() ? localFileHeader.dateTimeModified * 1000L
099            : ZipUtil.dosToJavaTime(0xFFFFFFFFL & localFileHeader.dateTimeModified);
100        return new Date(ts);
101    }
102
103    int getMethod() {
104        return localFileHeader.method;
105    }
106
107    /**
108     * File mode of this entry.
109     *
110     * <p>The format depends on the host os that created the entry.</p>
111     *
112     * @return the file mode
113     */
114    public int getMode() {
115        return localFileHeader.fileAccessMode;
116    }
117
118    /**
119     * Get this entry's name.
120     *
121     * <p>This method returns the raw name as it is stored inside of the archive.</p>
122     *
123     * @return This entry's name.
124     */
125    @Override
126    public String getName() {
127        if ((localFileHeader.arjFlags & LocalFileHeader.Flags.PATHSYM) != 0) {
128            return localFileHeader.name.replace("/",
129                    File.separator);
130        }
131        return localFileHeader.name;
132    }
133
134    /**
135     * Get this entry's file size.
136     *
137     * @return This entry's file size.
138     */
139    @Override
140    public long getSize() {
141        return localFileHeader.originalSize;
142    }
143
144    /**
145     * File mode of this entry as Unix stat value.
146     *
147     * <p>Will only be non-zero of the host os was UNIX.
148     *
149     * @return the Unix mode
150     */
151    public int getUnixMode() {
152        return isHostOsUnix() ? getMode() : 0;
153    }
154
155    @Override
156    public int hashCode() {
157        final String name = getName();
158        return name == null ? 0 : name.hashCode();
159    }
160
161    /** True if the entry refers to a directory.
162     *
163     * @return True if the entry refers to a directory
164     */
165    @Override
166    public boolean isDirectory() {
167        return localFileHeader.fileType == LocalFileHeader.FileTypes.DIRECTORY;
168    }
169
170    /**
171     * Is the operating system the archive has been created on one
172     * that is considered a UNIX OS by arj?
173     * @return whether the operating system the archive has been
174     * created on is considered a UNIX OS by arj
175     */
176    public boolean isHostOsUnix() {
177        return getHostOs() == HostOs.UNIX || getHostOs() == HostOs.NEXT;
178    }
179
180}