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