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.pack200;
20
21 import java.io.IOException;
22 import java.io.OutputStream;
23
24
25
26
27 public class SegmentHeader extends BandSet {
28
29
30
31
32 private static final class Counter {
33
34 private final int[] objs = new int[8];
35 private final int[] counts = new int[8];
36 private int length;
37
38 public void add(final int obj) {
39 boolean found = false;
40 for (int i = 0; i < length; i++) {
41 if (objs[i] == obj) {
42 counts[i]++;
43 found = true;
44 }
45 }
46 if (!found) {
47 objs[length] = obj;
48 counts[length] = 1;
49 length++;
50 if (length > objs.length - 1) {
51 final Object[] newArray = new Object[objs.length + 8];
52 System.arraycopy(objs, 0, newArray, 0, length);
53 }
54 }
55 }
56
57 public int getMostCommon() {
58 int returnIndex = 0;
59 for (int i = 0; i < length; i++) {
60 if (counts[i] > counts[returnIndex]) {
61 returnIndex = i;
62 }
63 }
64 return objs[returnIndex];
65 }
66 }
67
68 private static final int[] magic = { 0xCA, 0xFE, 0xD0, 0x0D };
69 private static final int archive_minver = 7;
70 private static final int archive_majver = 150;
71
72 private int archive_options;
73
74 private int cp_Utf8_count;
75 private int cp_Int_count;
76 private int cp_Float_count;
77 private int cp_Long_count;
78 private int cp_Double_count;
79 private int cp_String_count;
80 private int cp_Class_count;
81 private int cp_Signature_count;
82 private int cp_Descr_count;
83 private int cp_Field_count;
84 private int cp_Method_count;
85 private int cp_Imethod_count;
86
87 private int attribute_definition_count;
88 private final IntList band_headers = new IntList();
89
90 private boolean have_all_code_flags = true;
91
92 private int archive_size_hi;
93 private int archive_size_lo;
94 private int archive_next_count;
95 private int archive_modtime;
96 private int file_count;
97
98 private boolean deflate_hint;
99 private final boolean have_file_modtime = true;
100 private final boolean have_file_options = true;
101 private boolean have_file_size_hi;
102 private boolean have_class_flags_hi;
103 private boolean have_field_flags_hi;
104 private boolean have_method_flags_hi;
105 private boolean have_code_flags_hi;
106
107 private int ic_count;
108 private int class_count;
109 private final Counter majverCounter = new Counter();
110
111
112
113
114 public SegmentHeader() {
115 super(1, null);
116
117 }
118
119 public void addMajorVersion(final int major) {
120 majverCounter.add(major);
121 }
122
123 public void appendBandCodingSpecifier(final int specifier) {
124 band_headers.add(specifier);
125 }
126
127 private void calculateArchiveOptions() {
128 if (attribute_definition_count > 0 || band_headers.size() > 0) {
129 archive_options |= 1;
130 }
131 if (cp_Int_count > 0 || cp_Float_count > 0 || cp_Long_count > 0 || cp_Double_count > 0) {
132 archive_options |= 1 << 1;
133 }
134 if (have_all_code_flags) {
135 archive_options |= 1 << 2;
136 }
137 if (file_count > 0) {
138 archive_options |= 1 << 4;
139 }
140 if (deflate_hint) {
141 archive_options |= 1 << 5;
142 }
143 if (have_file_modtime) {
144 archive_options |= 1 << 6;
145 }
146 if (have_file_options) {
147 archive_options |= 1 << 7;
148 }
149 if (have_file_size_hi) {
150 archive_options |= 1 << 8;
151 }
152 if (have_class_flags_hi) {
153 archive_options |= 1 << 9;
154 }
155 if (have_field_flags_hi) {
156 archive_options |= 1 << 10;
157 }
158 if (have_method_flags_hi) {
159 archive_options |= 1 << 11;
160 }
161 if (have_code_flags_hi) {
162 archive_options |= 1 << 12;
163 }
164 }
165
166 public int getArchive_modtime() {
167 return archive_modtime;
168 }
169
170 public int getDefaultMajorVersion() {
171 return majverCounter.getMostCommon();
172 }
173
174 public boolean have_all_code_flags() {
175 return have_all_code_flags;
176 }
177
178 public boolean have_class_flags_hi() {
179 return have_class_flags_hi;
180 }
181
182 public boolean have_code_flags_hi() {
183 return have_code_flags_hi;
184 }
185
186 public boolean have_field_flags_hi() {
187 return have_field_flags_hi;
188 }
189
190 public boolean have_file_modtime() {
191 return have_file_modtime;
192 }
193
194 public boolean have_file_options() {
195 return have_file_options;
196 }
197
198 public boolean have_file_size_hi() {
199 return have_file_size_hi;
200 }
201
202 public boolean have_method_flags_hi() {
203 return have_method_flags_hi;
204 }
205
206
207
208
209 @Override
210 public void pack(final OutputStream out) throws IOException, Pack200Exception {
211 out.write(encodeScalar(magic, Codec.BYTE1));
212 out.write(encodeScalar(archive_minver, Codec.UNSIGNED5));
213 out.write(encodeScalar(archive_majver, Codec.UNSIGNED5));
214 calculateArchiveOptions();
215 out.write(encodeScalar(archive_options, Codec.UNSIGNED5));
216 writeArchiveFileCounts(out);
217 writeArchiveSpecialCounts(out);
218 writeCpCounts(out);
219 writeClassCounts(out);
220 if (band_headers.size() > 0) {
221 out.write(encodeScalar(band_headers.toArray(), Codec.BYTE1));
222 }
223 }
224
225 public void setAttribute_definition_count(final int attribute_definition_count) {
226 this.attribute_definition_count = attribute_definition_count;
227 }
228
229 public void setClass_count(final int class_count) {
230 this.class_count = class_count;
231 }
232
233 public void setCp_Class_count(final int count) {
234 cp_Class_count = count;
235 }
236
237 public void setCp_Descr_count(final int count) {
238 cp_Descr_count = count;
239 }
240
241 public void setCp_Double_count(final int count) {
242 cp_Double_count = count;
243 }
244
245 public void setCp_Field_count(final int count) {
246 cp_Field_count = count;
247 }
248
249 public void setCp_Float_count(final int count) {
250 cp_Float_count = count;
251 }
252
253 public void setCp_Imethod_count(final int count) {
254 cp_Imethod_count = count;
255 }
256
257 public void setCp_Int_count(final int count) {
258 cp_Int_count = count;
259 }
260
261 public void setCp_Long_count(final int count) {
262 cp_Long_count = count;
263 }
264
265 public void setCp_Method_count(final int count) {
266 cp_Method_count = count;
267 }
268
269 public void setCp_Signature_count(final int count) {
270 cp_Signature_count = count;
271 }
272
273 public void setCp_String_count(final int count) {
274 cp_String_count = count;
275 }
276
277 public void setCp_Utf8_count(final int count) {
278 cp_Utf8_count = count;
279 }
280
281 public void setDeflate_hint(final boolean deflate_hint) {
282 this.deflate_hint = deflate_hint;
283 }
284
285 public void setFile_count(final int file_count) {
286 this.file_count = file_count;
287 }
288
289 public void setHave_all_code_flags(final boolean have_all_code_flags) {
290 this.have_all_code_flags = have_all_code_flags;
291 }
292
293 public void setHave_class_flags_hi(final boolean have_class_flags_hi) {
294 this.have_class_flags_hi = have_class_flags_hi;
295 }
296
297 public void setHave_code_flags_hi(final boolean have_code_flags_hi) {
298 this.have_code_flags_hi = have_code_flags_hi;
299 }
300
301 public void setHave_field_flags_hi(final boolean have_field_flags_hi) {
302 this.have_field_flags_hi = have_field_flags_hi;
303 }
304
305 public void setHave_method_flags_hi(final boolean have_method_flags_hi) {
306 this.have_method_flags_hi = have_method_flags_hi;
307 }
308
309 public void setIc_count(final int ic_count) {
310 this.ic_count = ic_count;
311 }
312
313 private void writeArchiveFileCounts(final OutputStream out) throws IOException, Pack200Exception {
314 if ((archive_options & 1 << 4) > 0) {
315 out.write(encodeScalar(archive_size_hi, Codec.UNSIGNED5));
316 out.write(encodeScalar(archive_size_lo, Codec.UNSIGNED5));
317 out.write(encodeScalar(archive_next_count, Codec.UNSIGNED5));
318 out.write(encodeScalar(archive_modtime, Codec.UNSIGNED5));
319 out.write(encodeScalar(file_count, Codec.UNSIGNED5));
320 }
321 }
322
323 private void writeArchiveSpecialCounts(final OutputStream out) throws IOException, Pack200Exception {
324 if ((archive_options & 1) > 0) {
325 out.write(encodeScalar(band_headers.size(), Codec.UNSIGNED5));
326 out.write(encodeScalar(attribute_definition_count, Codec.UNSIGNED5));
327 }
328 }
329
330 private void writeClassCounts(final OutputStream out) throws IOException, Pack200Exception {
331 final int default_class_minver = 0;
332 final int default_class_majver = majverCounter.getMostCommon();
333 out.write(encodeScalar(ic_count, Codec.UNSIGNED5));
334 out.write(encodeScalar(default_class_minver, Codec.UNSIGNED5));
335 out.write(encodeScalar(default_class_majver, Codec.UNSIGNED5));
336 out.write(encodeScalar(class_count, Codec.UNSIGNED5));
337 }
338
339 private void writeCpCounts(final OutputStream out) throws IOException, Pack200Exception {
340 out.write(encodeScalar(cp_Utf8_count, Codec.UNSIGNED5));
341 if ((archive_options & 1 << 1) != 0) {
342 out.write(encodeScalar(cp_Int_count, Codec.UNSIGNED5));
343 out.write(encodeScalar(cp_Float_count, Codec.UNSIGNED5));
344 out.write(encodeScalar(cp_Long_count, Codec.UNSIGNED5));
345 out.write(encodeScalar(cp_Double_count, Codec.UNSIGNED5));
346 }
347 out.write(encodeScalar(cp_String_count, Codec.UNSIGNED5));
348 out.write(encodeScalar(cp_Class_count, Codec.UNSIGNED5));
349 out.write(encodeScalar(cp_Signature_count, Codec.UNSIGNED5));
350 out.write(encodeScalar(cp_Descr_count, Codec.UNSIGNED5));
351 out.write(encodeScalar(cp_Field_count, Codec.UNSIGNED5));
352 out.write(encodeScalar(cp_Method_count, Codec.UNSIGNED5));
353 out.write(encodeScalar(cp_Imethod_count, Codec.UNSIGNED5));
354 }
355
356 }