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