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 correspondanding 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 correspondanding 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 }