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     * @see HostOs
124     * @return the host OS code
125     */
126    public int getHostOs() {
127        return localFileHeader.hostOS;
128    }
129
130    /**
131     * The last modified date of the entry.
132     *
133     * <p>Note the interpretation of time is different depending on
134     * the HostOS that has created the archive.  While an OS that is
135     * {@link #isHostOsUnix considered to be Unix} stores time in a
136     * time zone independent manner, other platforms only use the local
137     * time.  I.e. if an archive has been created at midnight UTC on a
138     * machine in time zone UTC this method will return midnight
139     * regardless of time zone if the archive has been created on a
140     * non-Unix system and a time taking the current time zone into
141     * account if the archive has been created on Unix.</p>
142     *
143     * @return the last modified date
144     */
145    @Override
146    public Date getLastModifiedDate() {
147        final long ts = isHostOsUnix() ? localFileHeader.dateTimeModified * 1000L
148            : ZipUtil.dosToJavaTime(0xFFFFFFFFL & localFileHeader.dateTimeModified);
149        return new Date(ts);
150    }
151
152    int getMethod() {
153        return localFileHeader.method;
154    }
155
156    /**
157     * File mode of this entry.
158     *
159     * <p>The format depends on the host os that created the entry.</p>
160     *
161     * @return the file mode
162     */
163    public int getMode() {
164        return localFileHeader.fileAccessMode;
165    }
166
167    /**
168     * Gets this entry's name.
169     *
170     * <p>This method returns the raw name as it is stored inside of the archive.</p>
171     *
172     * @return This entry's name.
173     */
174    @Override
175    public String getName() {
176        if ((localFileHeader.arjFlags & LocalFileHeader.Flags.PATHSYM) != 0) {
177            return localFileHeader.name.replace("/",
178                    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>Will only be non-zero of the host os was UNIX.
197     *
198     * @return the Unix mode
199     */
200    public int getUnixMode() {
201        return isHostOsUnix() ? getMode() : 0;
202    }
203
204    @Override
205    public int hashCode() {
206        final String name = getName();
207        return name == null ? 0 : name.hashCode();
208    }
209
210    /** True if the entry refers to a directory.
211     *
212     * @return True if the entry refers to a directory
213     */
214    @Override
215    public boolean isDirectory() {
216        return localFileHeader.fileType == LocalFileHeader.FileTypes.DIRECTORY;
217    }
218
219    /**
220     * Is the operating system the archive has been created on one
221     * that is considered a UNIX OS by arj?
222     * @return whether the operating system the archive has been
223     * created on is considered a UNIX OS by arj
224     */
225    public boolean isHostOsUnix() {
226        return getHostOs() == HostOs.UNIX || getHostOs() == HostOs.NEXT;
227    }
228
229}