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 }