View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one or more
3    *  contributor license agreements.  See the NOTICE file distributed with
4    *  this work for additional information regarding copyright ownership.
5    *  The ASF licenses this file to You under the Apache License, Version 2.0
6    *  (the "License"); you may not use this file except in compliance with
7    *  the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   */
17  package org.apache.commons.compress.harmony.unpack200;
18  
19  import java.io.IOException;
20  import java.io.InputStream;
21  
22  import org.apache.commons.compress.harmony.pack200.Codec;
23  import org.apache.commons.compress.harmony.pack200.Pack200Exception;
24  import org.apache.commons.compress.utils.IOUtils;
25  
26  /**
27   * Parses the file band headers (not including the actual bits themselves). At the end of this parse call, the input stream will be positioned at the start of
28   * the file_bits themselves, and there will be Sum(file_size) bits remaining in the stream with BYTE1 compression. A decent implementation will probably just
29   * stream the bytes out to the reconstituted Jar rather than caching them.
30   */
31  public class FileBands extends BandSet {
32  
33      private byte[][] fileBits;
34  
35      private int[] fileModtime;
36  
37      private String[] fileName;
38  
39      private int[] fileOptions;
40  
41      private long[] fileSize;
42  
43      private final String[] cpUTF8;
44  
45      private InputStream in;
46  
47      /**
48       * @param segment TODO
49       */
50      public FileBands(final Segment segment) {
51          super(segment);
52          this.cpUTF8 = segment.getCpBands().getCpUTF8();
53      }
54  
55      public byte[][] getFileBits() {
56          return fileBits;
57      }
58  
59      public int[] getFileModtime() {
60          return fileModtime;
61      }
62  
63      public String[] getFileName() {
64          return fileName;
65      }
66  
67      public int[] getFileOptions() {
68          return fileOptions;
69      }
70  
71      public long[] getFileSize() {
72          return fileSize;
73      }
74  
75      // TODO: stream the file bits directly somehow
76      public void processFileBits() throws IOException {
77          // now read in the bytes
78          final int numberOfFiles = header.getNumberOfFiles();
79          fileBits = new byte[numberOfFiles][];
80          for (int i = 0; i < numberOfFiles; i++) {
81              final int size = (int) fileSize[i];
82              fileBits[i] = IOUtils.readRange(in, size);
83              final int read = fileBits[i].length;
84              if (size != 0 && read < size) {
85                  throw new IOException("Expected to read " + size + " bytes but read " + read);
86              }
87          }
88      }
89  
90      /*
91       * (non-Javadoc)
92       *
93       * @see org.apache.commons.compress.harmony.unpack200.BandSet#unpack(java.io.InputStream)
94       */
95      @Override
96      public void read(final InputStream in) throws IOException, Pack200Exception {
97          final int numberOfFiles = header.getNumberOfFiles();
98          final SegmentOptions options = header.getOptions();
99  
100         fileName = parseReferences("file_name", in, Codec.UNSIGNED5, numberOfFiles, cpUTF8);
101         fileSize = parseFlags("file_size", in, numberOfFiles, Codec.UNSIGNED5, options.hasFileSizeHi());
102         if (options.hasFileModtime()) {
103             fileModtime = decodeBandInt("file_modtime", in, Codec.DELTA5, numberOfFiles);
104         } else {
105             fileModtime = new int[numberOfFiles];
106         }
107         if (options.hasFileOptions()) {
108             fileOptions = decodeBandInt("file_options", in, Codec.UNSIGNED5, numberOfFiles);
109         } else {
110             fileOptions = new int[numberOfFiles];
111         }
112         this.in = in; // store for use by processFileBits(), which is called
113         // later
114     }
115 
116     @Override
117     public void unpack() {
118 
119     }
120 
121 }