1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.compress.harmony.pack200;
18
19 import java.io.IOException;
20 import java.io.OutputStream;
21 import java.util.Arrays;
22 import java.util.HashSet;
23 import java.util.List;
24 import java.util.Set;
25 import java.util.TimeZone;
26
27 import org.apache.commons.compress.harmony.pack200.Archive.PackingFile;
28 import org.apache.commons.compress.harmony.pack200.Archive.SegmentUnit;
29 import org.apache.commons.compress.utils.ExactMath;
30 import org.objectweb.asm.ClassReader;
31
32
33
34
35
36 public class FileBands extends BandSet {
37
38 private final CPUTF8[] fileName;
39 private int[] file_name;
40 private final int[] file_modtime;
41 private final long[] file_size;
42 private final int[] file_options;
43 private final byte[][] file_bits;
44 private final List<PackingFile> fileList;
45 private final PackingOptions options;
46 private final CpBands cpBands;
47
48 public FileBands(final CpBands cpBands, final SegmentHeader segmentHeader, final PackingOptions options, final SegmentUnit segmentUnit, final int effort) {
49 super(effort, segmentHeader);
50 fileList = segmentUnit.getFileList();
51 this.options = options;
52 this.cpBands = cpBands;
53 final int size = fileList.size();
54 fileName = new CPUTF8[size];
55 file_modtime = new int[size];
56 file_size = new long[size];
57 file_options = new int[size];
58 int totalSize = 0;
59 file_bits = new byte[size][];
60 final int archiveModtime = segmentHeader.getArchive_modtime();
61
62 final Set<String> classNames = new HashSet<>();
63 for (final ClassReader reader : segmentUnit.getClassList()) {
64 classNames.add(reader.getClassName());
65 }
66 final CPUTF8 emptyString = cpBands.getCPUtf8("");
67 long modtime;
68 int latestModtime = Integer.MIN_VALUE;
69 final boolean isLatest = !PackingOptions.KEEP.equals(options.getModificationTime());
70 for (int i = 0; i < size; i++) {
71 final PackingFile packingFile = fileList.get(i);
72 final String name = packingFile.getName();
73 if (name.endsWith(".class") && !options.isPassFile(name)) {
74 file_options[i] |= 1 << 1;
75 if (classNames.contains(name.substring(0, name.length() - 6))) {
76 fileName[i] = emptyString;
77 } else {
78 fileName[i] = cpBands.getCPUtf8(name);
79 }
80 } else {
81 fileName[i] = cpBands.getCPUtf8(name);
82 }
83
84 if (options.isKeepDeflateHint() && packingFile.isDefalteHint()) {
85 file_options[i] |= 0x1;
86 }
87 final byte[] bytes = packingFile.getContents();
88 file_size[i] = bytes.length;
89 totalSize = ExactMath.add(totalSize, file_size[i]);
90
91
92 modtime = (packingFile.getModtime() + TimeZone.getDefault().getRawOffset()) / 1000L;
93 file_modtime[i] = (int) (modtime - archiveModtime);
94 if (isLatest && latestModtime < file_modtime[i]) {
95 latestModtime = file_modtime[i];
96 }
97
98 file_bits[i] = packingFile.getContents();
99 }
100
101 if (isLatest) {
102 Arrays.fill(file_modtime, latestModtime);
103 }
104 }
105
106
107
108
109
110 public void finaliseBands() {
111 file_name = new int[fileName.length];
112 for (int i = 0; i < file_name.length; i++) {
113 if (fileName[i].equals(cpBands.getCPUtf8(""))) {
114 final PackingFile packingFile = fileList.get(i);
115 final String name = packingFile.getName();
116 if (options.isPassFile(name)) {
117 fileName[i] = cpBands.getCPUtf8(name);
118 file_options[i] &= 1 << 1 ^ 0xFFFFFFFF;
119 }
120 }
121 file_name[i] = fileName[i].getIndex();
122 }
123 }
124
125 private int[] flatten(final byte[][] bytes) {
126 int total = 0;
127 for (final byte[] element : bytes) {
128 total += element.length;
129 }
130 final int[] band = new int[total];
131 int index = 0;
132 for (final byte[] element : bytes) {
133 for (final byte element2 : element) {
134 band[index++] = element2 & 0xFF;
135 }
136 }
137 return band;
138 }
139
140 @Override
141 public void pack(final OutputStream out) throws IOException, Pack200Exception {
142 PackingUtils.log("Writing file bands...");
143 byte[] encodedBand = encodeBandInt("file_name", file_name, Codec.UNSIGNED5);
144 out.write(encodedBand);
145 PackingUtils.log("Wrote " + encodedBand.length + " bytes from file_name[" + file_name.length + "]");
146
147 encodedBand = encodeFlags("file_size", file_size, Codec.UNSIGNED5, Codec.UNSIGNED5, segmentHeader.have_file_size_hi());
148 out.write(encodedBand);
149 PackingUtils.log("Wrote " + encodedBand.length + " bytes from file_size[" + file_size.length + "]");
150
151 if (segmentHeader.have_file_modtime()) {
152 encodedBand = encodeBandInt("file_modtime", file_modtime, Codec.DELTA5);
153 out.write(encodedBand);
154 PackingUtils.log("Wrote " + encodedBand.length + " bytes from file_modtime[" + file_modtime.length + "]");
155 }
156 if (segmentHeader.have_file_options()) {
157 encodedBand = encodeBandInt("file_options", file_options, Codec.UNSIGNED5);
158 out.write(encodedBand);
159 PackingUtils.log("Wrote " + encodedBand.length + " bytes from file_options[" + file_options.length + "]");
160 }
161
162 encodedBand = encodeBandInt("file_bits", flatten(file_bits), Codec.BYTE1);
163 out.write(encodedBand);
164 PackingUtils.log("Wrote " + encodedBand.length + " bytes from file_bits[" + file_bits.length + "]");
165 }
166
167 }