001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.harmony.pack200;
018:
019: import java.io.IOException;
020: import java.io.InputStream;
021:
022: /**
023: * Parses the file band headers (not including the actual bits themselves).
024: * At the end of this parse call, the input stream will be positioned at the
025: * start of the file_bits themselves, and there will be Sum(file_size) bits
026: * remaining in the stream with BYTE1 compression. A decent implementation
027: * will probably just stream the bytes out to the reconstituted Jar rather
028: * than caching them.
029: */
030: public class FileBands extends BandSet {
031:
032: private byte[][] fileBits;
033:
034: private long[] fileModtime;
035:
036: private String[] fileName;
037:
038: private long[] fileOptions;
039:
040: private long[] fileSize;
041:
042: private String[] cpUTF8;
043:
044: private InputStream in;
045:
046: /**
047: * @param header
048: */
049: public FileBands(Segment segment) {
050: super (segment);
051: this .cpUTF8 = segment.getCpBands().getCpUTF8();
052: }
053:
054: /* (non-Javadoc)
055: * @see org.apache.harmony.pack200.BandSet#unpack(java.io.InputStream)
056: */
057: public void unpack(InputStream in) throws IOException,
058: Pack200Exception {
059: int numberOfFiles = header.getNumberOfFiles();
060: SegmentOptions options = header.getOptions();
061:
062: fileName = parseReferences("file_name", in, Codec.UNSIGNED5,
063: numberOfFiles, cpUTF8);
064: fileSize = parseFlags("file_size", in, numberOfFiles,
065: Codec.UNSIGNED5, options.hasFileSizeHi());
066: if (options.hasFileModtime()) {
067: fileModtime = decodeBandLong("file_modtime", in,
068: Codec.DELTA5, numberOfFiles);
069: } else {
070: fileModtime = new long[numberOfFiles];
071: }
072: if (options.hasFileOptions()) {
073: fileOptions = decodeBandLong("file_options", in,
074: Codec.UNSIGNED5, numberOfFiles);
075: } else {
076: fileOptions = new long[numberOfFiles];
077: }
078: this .in = in; // store for use by processFileBits(), which is called later
079: }
080:
081: // TODO: stream the file bits directly somehow
082: public void processFileBits() throws IOException, Pack200Exception {
083: // now read in the bytes
084: int numberOfFiles = header.getNumberOfFiles();
085: fileBits = new byte[numberOfFiles][];
086: for (int i = 0; i < numberOfFiles; i++) {
087: int size = (int) fileSize[i];
088: // TODO This breaks if file_size > 2^32. Probably an array is
089: // not the right choice, and we should just serialize it here?
090: fileBits[i] = new byte[size];
091: int read = in.read(fileBits[i]);
092: if (read < size) {
093: throw new Pack200Exception("Expected to read " + size
094: + " bytes but read " + read);
095: }
096: }
097: }
098:
099: public byte[][] getFileBits() {
100: return fileBits;
101: }
102:
103: public long[] getFileModtime() {
104: return fileModtime;
105: }
106:
107: public String[] getFileName() {
108: return fileName;
109: }
110:
111: public long[] getFileOptions() {
112: return fileOptions;
113: }
114:
115: public long[] getFileSize() {
116: return fileSize;
117: }
118:
119: }
|