You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
183 lines
7.0 KiB
183 lines
7.0 KiB
/*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership.
|
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
* (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
package org.apache.harmony.pack200;
|
|
|
|
import java.io.IOException;
|
|
import java.io.OutputStream;
|
|
import java.util.HashSet;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.Set;
|
|
import java.util.TimeZone;
|
|
|
|
import org.apache.harmony.pack200.Archive.PackingFile;
|
|
import org.apache.harmony.pack200.Archive.SegmentUnit;
|
|
import org.objectweb.asm.ClassReader;
|
|
|
|
/**
|
|
* Bands containing information about files in the pack200 archive and the file
|
|
* contents for non-class-files. Corresponds to the <code>file_bands</code> set
|
|
* of bands described in the specification.
|
|
*/
|
|
public class FileBands extends BandSet {
|
|
|
|
private final CPUTF8[] fileName;
|
|
private int[] file_name;
|
|
private final int[] file_modtime;
|
|
private final long[] file_size;
|
|
private final int[] file_options;
|
|
private final byte[][] file_bits;
|
|
private final List fileList;
|
|
private final PackingOptions options;
|
|
private final CpBands cpBands;
|
|
|
|
public FileBands(CpBands cpBands, SegmentHeader segmentHeader,
|
|
PackingOptions options, SegmentUnit segmentUnit, int effort) {
|
|
super(effort, segmentHeader);
|
|
fileList = segmentUnit.getFileList();
|
|
this.options = options;
|
|
this.cpBands = cpBands;
|
|
int size = fileList.size();
|
|
fileName = new CPUTF8[size];
|
|
file_modtime = new int[size];
|
|
file_size = new long[size];
|
|
file_options = new int[size];
|
|
int totalSize = 0;
|
|
file_bits = new byte[size][];
|
|
int archiveModtime = segmentHeader.getArchive_modtime();
|
|
|
|
Set classNames = new HashSet();
|
|
for (Iterator iterator = segmentUnit.getClassList().iterator(); iterator
|
|
.hasNext();) {
|
|
ClassReader reader = (ClassReader) iterator.next();
|
|
classNames.add(reader.getClassName());
|
|
}
|
|
CPUTF8 emptyString = cpBands.getCPUtf8("");
|
|
long modtime;
|
|
int latestModtime = Integer.MIN_VALUE;
|
|
boolean isLatest = !PackingOptions.KEEP.equals(options
|
|
.getModificationTime());
|
|
for (int i = 0; i < size; i++) {
|
|
PackingFile packingFile = (PackingFile) fileList.get(i);
|
|
String name = packingFile.getName();
|
|
if (name.endsWith(".class") && !options.isPassFile(name)) {
|
|
file_options[i] |= (1 << 1);
|
|
if (classNames.contains(name.substring(0, name.length() - 6))) {
|
|
fileName[i] = emptyString;
|
|
} else {
|
|
fileName[i] = cpBands.getCPUtf8(name);
|
|
}
|
|
} else {
|
|
fileName[i] = cpBands.getCPUtf8(name);
|
|
}
|
|
// set deflate_hint for file element
|
|
if (options.isKeepDeflateHint() && packingFile.isDefalteHint()) {
|
|
file_options[i] |= 0x1;
|
|
}
|
|
byte[] bytes = packingFile.getContents();
|
|
file_size[i] = bytes.length;
|
|
totalSize += file_size[i];
|
|
|
|
// update modification time
|
|
modtime = (packingFile.getModtime() + TimeZone.getDefault().getRawOffset()) / 1000L;
|
|
file_modtime[i] = (int) (modtime - archiveModtime);
|
|
if (isLatest && latestModtime < file_modtime[i]) {
|
|
latestModtime = file_modtime[i];
|
|
}
|
|
|
|
file_bits[i] = packingFile.getContents();
|
|
}
|
|
|
|
if (isLatest) {
|
|
for (int index = 0; index < size; index++) {
|
|
file_modtime[index] = latestModtime;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* All input classes for the segment have now been read in, so this method
|
|
* is called so that this class can calculate/complete anything it could not
|
|
* do while classes were being read.
|
|
*/
|
|
public void finaliseBands() {
|
|
file_name = new int[fileName.length];
|
|
for (int i = 0; i < file_name.length; i++) {
|
|
if (fileName[i].equals(cpBands.getCPUtf8(""))) {
|
|
PackingFile packingFile = (PackingFile) fileList.get(i);
|
|
String name = packingFile.getName();
|
|
if (options.isPassFile(name)) {
|
|
fileName[i] = cpBands.getCPUtf8(name);
|
|
file_options[i] &= (1 << 1) ^ 0xFFFFFFFF;
|
|
}
|
|
}
|
|
file_name[i] = fileName[i].getIndex();
|
|
}
|
|
}
|
|
|
|
public void pack(OutputStream out) throws IOException, Pack200Exception {
|
|
PackingUtils.log("Writing file bands...");
|
|
byte[] encodedBand = encodeBandInt("file_name", file_name,
|
|
Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from file_name[" + file_name.length + "]");
|
|
|
|
encodedBand = encodeFlags("file_size", file_size, Codec.UNSIGNED5,
|
|
Codec.UNSIGNED5, segmentHeader.have_file_size_hi());
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from file_size[" + file_size.length + "]");
|
|
|
|
if (segmentHeader.have_file_modtime()) {
|
|
encodedBand = encodeBandInt("file_modtime", file_modtime,
|
|
Codec.DELTA5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from file_modtime[" + file_modtime.length + "]");
|
|
}
|
|
if (segmentHeader.have_file_options()) {
|
|
encodedBand = encodeBandInt("file_options", file_options,
|
|
Codec.UNSIGNED5);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from file_options[" + file_options.length + "]");
|
|
}
|
|
|
|
encodedBand = encodeBandInt("file_bits", flatten(file_bits),
|
|
Codec.BYTE1);
|
|
out.write(encodedBand);
|
|
PackingUtils.log("Wrote " + encodedBand.length
|
|
+ " bytes from file_bits[" + file_bits.length + "]");
|
|
}
|
|
|
|
private int[] flatten(byte[][] bytes) {
|
|
int total = 0;
|
|
for (int i = 0; i < bytes.length; i++) {
|
|
total += bytes[i].length;
|
|
}
|
|
int[] band = new int[total];
|
|
int index = 0;
|
|
for (int i = 0; i < bytes.length; i++) {
|
|
for (int j = 0; j < bytes[i].length; j++) {
|
|
band[index++] = bytes[i][j] & 0xFF;
|
|
}
|
|
}
|
|
return band;
|
|
}
|
|
|
|
}
|
|
|