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