001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *   https://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.commons.compress.archivers.arj;
020
021import java.io.File;
022import java.util.Date;
023
024import org.apache.commons.compress.archivers.ArchiveEntry;
025import org.apache.commons.compress.archivers.zip.ZipUtil;
026
027/**
028 * An entry in an ARJ archive.
029 *
030 * @NotThreadSafe
031 * @since 1.6
032 */
033public class ArjArchiveEntry implements ArchiveEntry {
034
035    /**
036     * The known values for HostOs.
037     */
038    public static class HostOs {
039
040        /**
041         * Constant value {@value}.
042         */
043        public static final int DOS = 0;
044
045        /**
046         * Constant value {@value}.
047         */
048        public static final int PRIMOS = 1;
049
050        /**
051         * Constant value {@value}.
052         */
053        public static final int UNIX = 2;
054
055        /**
056         * Constant value {@value}.
057         */
058        public static final int AMIGA = 3;
059
060        /**
061         * Constant value {@value}.
062         */
063        public static final int MAC_OS = 4;
064
065        /**
066         * Constant value {@value}.
067         */
068        public static final int OS_2 = 5;
069
070        /**
071         * Constant value {@value}.
072         */
073        public static final int APPLE_GS = 6;
074
075        /**
076         * Constant value {@value}.
077         */
078        public static final int ATARI_ST = 7;
079
080        /**
081         * Constant value {@value}.
082         */
083        public static final int NEXT = 8;
084
085        /**
086         * Constant value {@value}.
087         */
088        public static final int VAX_VMS = 9;
089
090        /**
091         * Constant value {@value}.
092         */
093        public static final int WIN95 = 10;
094
095        /**
096         * Constant value {@value}.
097         */
098        public static final int WIN32 = 11;
099
100        /**
101         * Constructs a new instance.
102         *
103         * @deprecated Will be private in the next major release.
104         */
105        @Deprecated
106        public HostOs() {
107            // empty
108        }
109    }
110
111    private final LocalFileHeader localFileHeader;
112
113    /**
114     * Constructs a new instance.
115     */
116    public ArjArchiveEntry() {
117        localFileHeader = new LocalFileHeader();
118    }
119
120    /**
121     * Constructs a new instance.
122     */
123    ArjArchiveEntry(final LocalFileHeader localFileHeader) {
124        this.localFileHeader = localFileHeader;
125    }
126
127    @Override
128    public boolean equals(final Object obj) {
129        if (this == obj) {
130            return true;
131        }
132        if (obj == null || getClass() != obj.getClass()) {
133            return false;
134        }
135        final ArjArchiveEntry other = (ArjArchiveEntry) obj;
136        return localFileHeader.equals(other.localFileHeader);
137    }
138
139    /**
140     * The operating system the archive has been created on.
141     *
142     * @see HostOs
143     * @return the host OS code
144     */
145    public int getHostOs() {
146        return localFileHeader.hostOS;
147    }
148
149    /**
150     * The last modified date of the entry.
151     *
152     * <p>
153     * 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
154     * 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
155     * 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
156     * the current time zone into account if the archive has been created on Unix.
157     * </p>
158     *
159     * @return the last modified date
160     */
161    @Override
162    public Date getLastModifiedDate() {
163        final long ts = isHostOsUnix() ? localFileHeader.dateTimeModified * 1000L : ZipUtil.dosToJavaTime(0xFFFFFFFFL & localFileHeader.dateTimeModified);
164        return new Date(ts);
165    }
166
167    int getMethod() {
168        return localFileHeader.method;
169    }
170
171    /**
172     * File mode of this entry.
173     *
174     * <p>
175     * The format depends on the host os that created the entry.
176     * </p>
177     *
178     * @return the file mode
179     */
180    public int getMode() {
181        return localFileHeader.fileAccessMode;
182    }
183
184    /**
185     * Gets this entry's name.
186     *
187     * <p>
188     * This method returns the raw name as it is stored inside of the archive.
189     * </p>
190     *
191     * @return This entry's name.
192     */
193    @Override
194    public String getName() {
195        if ((localFileHeader.arjFlags & LocalFileHeader.Flags.PATHSYM) != 0) {
196            return localFileHeader.name.replace("/", File.separator);
197        }
198        return localFileHeader.name;
199    }
200
201    /**
202     * Gets this entry's file size.
203     *
204     * @return This entry's file size.
205     */
206    @Override
207    public long getSize() {
208        return localFileHeader.originalSize;
209    }
210
211    /**
212     * File mode of this entry as Unix stat value.
213     *
214     * <p>
215     * Will only be non-zero of the host os was Unix.
216     *
217     * @return the Unix mode
218     */
219    public int getUnixMode() {
220        return isHostOsUnix() ? getMode() : 0;
221    }
222
223    @Override
224    public int hashCode() {
225        final String name = getName();
226        return name == null ? 0 : name.hashCode();
227    }
228
229    /**
230     * True if the entry refers to a directory.
231     *
232     * @return True if the entry refers to a directory
233     */
234    @Override
235    public boolean isDirectory() {
236        return localFileHeader.fileType == LocalFileHeader.FileTypes.DIRECTORY;
237    }
238
239    /**
240     * Is the operating system the archive has been created on one that is considered a Unix OS by arj?
241     *
242     * @return whether the operating system the archive has been created on is considered a Unix OS by arj
243     */
244    public boolean isHostOsUnix() {
245        return getHostOs() == HostOs.UNIX || getHostOs() == HostOs.NEXT;
246    }
247
248}