1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.commons.compress.harmony.unpack200;
20
21 import java.io.ByteArrayInputStream;
22 import java.io.IOException;
23 import java.io.InputStream;
24
25 import org.apache.commons.compress.harmony.pack200.BHSDCodec;
26 import org.apache.commons.compress.harmony.pack200.Codec;
27 import org.apache.commons.compress.harmony.pack200.Pack200Exception;
28 import org.apache.commons.compress.utils.IOUtils;
29
30
31
32
33 public class SegmentHeader {
34
35 private static final byte[] EMPTY_BYTE_ARRAY = {};
36
37
38
39
40 private static final int[] magic = { 0xCA, 0xFE, 0xD0, 0x0D };
41
42 private int archiveMajor;
43
44 private int archiveMinor;
45
46 private long archiveModtime;
47
48 private long archiveSize;
49
50 private int attributeDefinitionCount;
51
52 private InputStream bandHeadersInputStream;
53
54 private int bandHeadersSize;
55
56 private int classCount;
57
58 private int cpClassCount;
59
60 private int cpDescriptorCount;
61
62 private int cpDoubleCount;
63
64 private int cpFieldCount;
65
66 private int cpFloatCount;
67
68 private int cpIMethodCount;
69
70 private int cpIntCount;
71
72 private int cpLongCount;
73
74 private int cpMethodCount;
75
76 private int cpSignatureCount;
77
78 private int cpStringCount;
79
80 private int cpUTF8Count;
81
82 private int defaultClassMajorVersion;
83
84 private int defaultClassMinorVersion;
85
86 private int innerClassCount;
87
88 private int numberOfFiles;
89
90 private int segmentsRemaining;
91
92 private SegmentOptions options;
93
94 private final Segment segment;
95
96 private int archiveSizeOffset;
97
98 public SegmentHeader(final Segment segment) {
99 this.segment = segment;
100 }
101
102
103
104
105
106
107
108
109
110
111
112 private int decodeScalar(final String name, final InputStream in, final BHSDCodec codec) throws IOException, Pack200Exception {
113 final int ret = codec.decode(in);
114 segment.log(Segment.LOG_LEVEL_VERBOSE, "Parsed #" + name + " as " + ret);
115 return ret;
116 }
117
118
119
120
121
122
123
124
125
126
127
128 private int[] decodeScalar(final String name, final InputStream in, final BHSDCodec codec, final int n) throws IOException, Pack200Exception {
129 segment.log(Segment.LOG_LEVEL_VERBOSE, "Parsed #" + name + " (" + n + ")");
130 return codec.decodeInts(n, in);
131 }
132
133 public long getArchiveModtime() {
134 return archiveModtime;
135 }
136
137 public long getArchiveSize() {
138 return archiveSize;
139 }
140
141 public int getArchiveSizeOffset() {
142 return archiveSizeOffset;
143 }
144
145 public int getAttributeDefinitionCount() {
146 return attributeDefinitionCount;
147 }
148
149
150
151
152
153
154
155
156
157
158 public InputStream getBandHeadersInputStream() {
159 if (bandHeadersInputStream == null) {
160 bandHeadersInputStream = new ByteArrayInputStream(EMPTY_BYTE_ARRAY);
161 }
162 return bandHeadersInputStream;
163
164 }
165
166 public int getBandHeadersSize() {
167 return bandHeadersSize;
168 }
169
170 public int getClassCount() {
171 return classCount;
172 }
173
174 public int getCpClassCount() {
175 return cpClassCount;
176 }
177
178 public int getCpDescriptorCount() {
179 return cpDescriptorCount;
180 }
181
182 public int getCpDoubleCount() {
183 return cpDoubleCount;
184 }
185
186 public int getCpFieldCount() {
187 return cpFieldCount;
188 }
189
190 public int getCpFloatCount() {
191 return cpFloatCount;
192 }
193
194 public int getCpIMethodCount() {
195 return cpIMethodCount;
196 }
197
198 public int getCpIntCount() {
199 return cpIntCount;
200 }
201
202 public int getCpLongCount() {
203 return cpLongCount;
204 }
205
206 public int getCpMethodCount() {
207 return cpMethodCount;
208 }
209
210 public int getCpSignatureCount() {
211 return cpSignatureCount;
212 }
213
214 public int getCpStringCount() {
215 return cpStringCount;
216 }
217
218 public int getCpUTF8Count() {
219 return cpUTF8Count;
220 }
221
222 public int getDefaultClassMajorVersion() {
223 return defaultClassMajorVersion;
224 }
225
226 public int getDefaultClassMinorVersion() {
227 return defaultClassMinorVersion;
228 }
229
230 public int getInnerClassCount() {
231 return innerClassCount;
232 }
233
234 public int getNumberOfFiles() {
235 return numberOfFiles;
236 }
237
238 public SegmentOptions getOptions() {
239 return options;
240 }
241
242 public int getSegmentsRemaining() {
243 return segmentsRemaining;
244 }
245
246 private void parseArchiveFileCounts(final InputStream in) throws IOException, Pack200Exception {
247 if (options.hasArchiveFileCounts()) {
248 setArchiveSize((long) decodeScalar("archive_size_hi", in, Codec.UNSIGNED5) << 32 | decodeScalar("archive_size_lo", in, Codec.UNSIGNED5));
249 archiveSizeOffset = in.available();
250 setSegmentsRemaining(decodeScalar("archive_next_count", in, Codec.UNSIGNED5));
251 setArchiveModtime(decodeScalar("archive_modtime", in, Codec.UNSIGNED5));
252 numberOfFiles = decodeScalar("file_count", in, Codec.UNSIGNED5);
253 }
254 }
255
256 private void parseArchiveSpecialCounts(final InputStream in) throws IOException, Pack200Exception {
257 if (getOptions().hasSpecialFormats()) {
258 bandHeadersSize = decodeScalar("band_headers_size", in, Codec.UNSIGNED5);
259 setAttributeDefinitionCount(decodeScalar("attr_definition_count", in, Codec.UNSIGNED5));
260 }
261 }
262
263 private void parseClassCounts(final InputStream in) throws IOException, Pack200Exception {
264 innerClassCount = decodeScalar("ic_count", in, Codec.UNSIGNED5);
265 defaultClassMinorVersion = decodeScalar("default_class_minver", in, Codec.UNSIGNED5);
266 defaultClassMajorVersion = decodeScalar("default_class_majver", in, Codec.UNSIGNED5);
267 classCount = decodeScalar("class_count", in, Codec.UNSIGNED5);
268 }
269
270 private void parseCpCounts(final InputStream in) throws IOException, Pack200Exception {
271 cpUTF8Count = decodeScalar("cp_Utf8_count", in, Codec.UNSIGNED5);
272 if (getOptions().hasCPNumberCounts()) {
273 cpIntCount = decodeScalar("cp_Int_count", in, Codec.UNSIGNED5);
274 cpFloatCount = decodeScalar("cp_Float_count", in, Codec.UNSIGNED5);
275 cpLongCount = decodeScalar("cp_Long_count", in, Codec.UNSIGNED5);
276 cpDoubleCount = decodeScalar("cp_Double_count", in, Codec.UNSIGNED5);
277 }
278 cpStringCount = decodeScalar("cp_String_count", in, Codec.UNSIGNED5);
279 cpClassCount = decodeScalar("cp_Class_count", in, Codec.UNSIGNED5);
280 cpSignatureCount = decodeScalar("cp_Signature_count", in, Codec.UNSIGNED5);
281 cpDescriptorCount = decodeScalar("cp_Descr_count", in, Codec.UNSIGNED5);
282 cpFieldCount = decodeScalar("cp_Field_count", in, Codec.UNSIGNED5);
283 cpMethodCount = decodeScalar("cp_Method_count", in, Codec.UNSIGNED5);
284 cpIMethodCount = decodeScalar("cp_Imethod_count", in, Codec.UNSIGNED5);
285 }
286
287 public void read(final InputStream in) throws IOException, Error, Pack200Exception {
288
289 final int[] word = decodeScalar("archive_magic_word", in, Codec.BYTE1, magic.length);
290 for (int m = 0; m < magic.length; m++) {
291 if (word[m] != magic[m]) {
292 throw new Error("Bad header");
293 }
294 }
295 setArchiveMinorVersion(decodeScalar("archive_minver", in, Codec.UNSIGNED5));
296 setArchiveMajorVersion(decodeScalar("archive_majver", in, Codec.UNSIGNED5));
297 options = new SegmentOptions(decodeScalar("archive_options", in, Codec.UNSIGNED5));
298 parseArchiveFileCounts(in);
299 parseArchiveSpecialCounts(in);
300 parseCpCounts(in);
301 parseClassCounts(in);
302
303 if (getBandHeadersSize() > 0) {
304 setBandHeadersData(IOUtils.readRange(in, getBandHeadersSize()));
305 }
306
307 archiveSizeOffset -= in.available();
308 }
309
310
311
312
313
314
315
316 private void setArchiveMajorVersion(final int version) throws Pack200Exception {
317 if (version != 150) {
318 throw new Pack200Exception("Invalid segment major version: " + version);
319 }
320 archiveMajor = version;
321 }
322
323
324
325
326
327
328
329 private void setArchiveMinorVersion(final int version) throws Pack200Exception {
330 if (version != 7) {
331 throw new Pack200Exception("Invalid segment minor version");
332 }
333 archiveMinor = version;
334 }
335
336 public void setArchiveModtime(final long archiveModtime) {
337 this.archiveModtime = archiveModtime;
338 }
339
340 public void setArchiveSize(final long archiveSize) {
341 this.archiveSize = archiveSize;
342 }
343
344 private void setAttributeDefinitionCount(final long valuie) {
345 this.attributeDefinitionCount = (int) valuie;
346 }
347
348 private void setBandHeadersData(final byte[] bandHeaders) {
349 this.bandHeadersInputStream = new ByteArrayInputStream(bandHeaders);
350 }
351
352 public void setSegmentsRemaining(final long value) {
353 segmentsRemaining = (int) value;
354 }
355
356 public void unpack() {
357
358 }
359 }