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