    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     *
    017     */
    018    package org.apache.commons.compress.archivers.zip;
    019
    020    /**
    021     * Utility class that represents a four byte integer with conversion
    022     * rules for the big endian byte order of ZIP files.
    023     * @Immutable
    024     */
    025    public final class ZipLong implements Cloneable {
    026
    027        private static final int WORD = 4;
    028        //private static final int BYTE_BIT_SIZE = 8;
    029        private static final int BYTE_MASK = 0xFF;
    030
    031        private static final int BYTE_1 = 1;
    032        private static final int BYTE_1_MASK = 0xFF00;
    033        private static final int BYTE_1_SHIFT = 8;
    034
    035        private static final int BYTE_2 = 2;
    036        private static final int BYTE_2_MASK = 0xFF0000;
    037        private static final int BYTE_2_SHIFT = 16;
    038
    039        private static final int BYTE_3 = 3;
    040        private static final long BYTE_3_MASK = 0xFF000000L;
    041        private static final int BYTE_3_SHIFT = 24;
    042
    043        private final long value;
    044
    045        /** Central File Header Signature */
    046        public static final ZipLong CFH_SIG = new ZipLong(0X02014B50L);
    047
    048        /** Local File Header Signature */
    049        public static final ZipLong LFH_SIG = new ZipLong(0X04034B50L);
    050
    051        /**
    052         * Data Descriptor signature
    053         * @since Apache Commons Compress 1.1
    054         */
    055        public static final ZipLong DD_SIG = new ZipLong(0X08074B50L);
    056
    057        /**
    058         * Create instance from a number.
    059         * @param value the long to store as a ZipLong
    060         */
    061        public ZipLong(long value) {
    062            this.value = value;
    063        }
    064
    065        /**
    066         * Create instance from bytes.
    067         * @param bytes the bytes to store as a ZipLong
    068         */
    069        public ZipLong (byte[] bytes) {
    070            this(bytes, 0);
    071        }
    072
    073        /**
    074         * Create instance from the four bytes starting at offset.
    075         * @param bytes the bytes to store as a ZipLong
    076         * @param offset the offset to start
    077         */
    078        public ZipLong (byte[] bytes, int offset) {
    079            value = ZipLong.getValue(bytes, offset);
    080        }
    081
    082        /**
    083         * Get value as four bytes in big endian byte order.
    084         * @return value as four bytes in big endian order
    085         */
    086        public byte[] getBytes() {
    087            return ZipLong.getBytes(value);
    088        }
    089
    090        /**
    091         * Get value as Java long.
    092         * @return value as a long
    093         */
    094        public long getValue() {
    095            return value;
    096        }
    097
    098        /**
    099         * Get value as four bytes in big endian byte order.
    100         * @param value the value to convert
    101         * @return value as four bytes in big endian byte order
    102         */
    103        public static byte[] getBytes(long value) {
    104            byte[] result = new byte[WORD];
    105            result[0] = (byte) ((value & BYTE_MASK));
    106            result[BYTE_1] = (byte) ((value & BYTE_1_MASK) >> BYTE_1_SHIFT);
    107            result[BYTE_2] = (byte) ((value & BYTE_2_MASK) >> BYTE_2_SHIFT);
    108            result[BYTE_3] = (byte) ((value & BYTE_3_MASK) >> BYTE_3_SHIFT);
    109            return result;
    110        }
    111
    112        /**
    113         * Helper method to get the value as a Java long from four bytes starting at given array offset
    114         * @param bytes the array of bytes
    115         * @param offset the offset to start
    116         * @return the corresponding Java long value
    117         */
    118        public static long getValue(byte[] bytes, int offset) {
    119            long value = (bytes[offset + BYTE_3] << BYTE_3_SHIFT) & BYTE_3_MASK;
    120            value += (bytes[offset + BYTE_2] << BYTE_2_SHIFT) & BYTE_2_MASK;
    121            value += (bytes[offset + BYTE_1] << BYTE_1_SHIFT) & BYTE_1_MASK;
    122            value += (bytes[offset] & BYTE_MASK);
    123            return value;
    124        }
    125
    126        /**
    127         * Helper method to get the value as a Java long from a four-byte array
    128         * @param bytes the array of bytes
    129         * @return the corresponding Java long value
    130         */
    131        public static long getValue(byte[] bytes) {
    132            return getValue(bytes, 0);
    133        }
    134
    135        /**
    136         * Override to make two instances with same value equal.
    137         * @param o an object to compare
    138         * @return true if the objects are equal
    139         */
    140        public boolean equals(Object o) {
    141            if (o == null || !(o instanceof ZipLong)) {
    142                return false;
    143            }
    144            return value == ((ZipLong) o).getValue();
    145        }
    146
    147        /**
    148         * Override to make two instances with same value equal.
    149         * @return the value stored in the ZipLong
    150         */
    151        public int hashCode() {
    152            return (int) value;
    153        }
    154
    155        public Object clone() {
    156            try {
    157                return super.clone();
    158            } catch (CloneNotSupportedException cnfe) {
    159                // impossible
    160                throw new RuntimeException(cnfe);
    161            }
    162        }
    163
    164        public String toString() {
    165            return "ZipLong value: " + value;
    166        }
    167    }