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