17
17
package org .springframework .boot .loader .jar ;
18
18
19
19
import java .io .IOException ;
20
- import java .io .InputStream ;
21
20
import java .util .Calendar ;
22
21
import java .util .GregorianCalendar ;
23
22
24
23
import org .springframework .boot .loader .data .RandomAccessData ;
25
- import org .springframework .boot .loader .data .RandomAccessData .ResourceAccess ;
26
24
27
25
/**
28
26
* A ZIP File "Central directory file header record" (CDFH).
@@ -36,26 +34,64 @@ final class CentralDirectoryFileHeader implements FileHeader {
36
34
37
35
private static final AsciiBytes SLASH = new AsciiBytes ("/" );
38
36
39
- private final byte [] header ;
37
+ private static final byte [] NO_EXTRA = {};
38
+
39
+ private static final AsciiBytes NO_COMMENT = new AsciiBytes ("" );
40
+
41
+ private byte [] header ;
42
+
43
+ private int headerOffset ;
40
44
41
45
private AsciiBytes name ;
42
46
43
- private final byte [] extra ;
47
+ private byte [] extra ;
44
48
45
- private final AsciiBytes comment ;
49
+ private AsciiBytes comment ;
46
50
47
- private final long localHeaderOffset ;
51
+ private long localHeaderOffset ;
48
52
49
- CentralDirectoryFileHeader (byte [] header , InputStream inputStream )
50
- throws IOException {
53
+ CentralDirectoryFileHeader () {
54
+ }
55
+
56
+ CentralDirectoryFileHeader (byte [] header , int headerOffset , AsciiBytes name ,
57
+ byte [] extra , AsciiBytes comment , long localHeaderOffset ) {
58
+ super ();
51
59
this .header = header ;
52
- long nameLength = Bytes .littleEndianValue (header , 28 , 2 );
53
- long extraLength = Bytes .littleEndianValue (header , 30 , 2 );
54
- long commentLength = Bytes .littleEndianValue (header , 32 , 2 );
55
- this .name = new AsciiBytes (Bytes .get (inputStream , nameLength ));
56
- this .extra = Bytes .get (inputStream , extraLength );
57
- this .comment = new AsciiBytes (Bytes .get (inputStream , commentLength ));
58
- this .localHeaderOffset = Bytes .littleEndianValue (header , 42 , 4 );
60
+ this .headerOffset = headerOffset ;
61
+ this .name = name ;
62
+ this .extra = extra ;
63
+ this .comment = comment ;
64
+ this .localHeaderOffset = localHeaderOffset ;
65
+ }
66
+
67
+ void load (byte [] data , int dataOffset , RandomAccessData variableData ,
68
+ int variableOffset ) throws IOException {
69
+ // Load fixed part
70
+ this .header = data ;
71
+ this .headerOffset = dataOffset ;
72
+ long nameLength = Bytes .littleEndianValue (data , dataOffset + 28 , 2 );
73
+ long extraLength = Bytes .littleEndianValue (data , dataOffset + 30 , 2 );
74
+ long commentLength = Bytes .littleEndianValue (data , dataOffset + 32 , 2 );
75
+ this .localHeaderOffset = Bytes .littleEndianValue (data , dataOffset + 42 , 4 );
76
+ // Load variable part
77
+ dataOffset += 46 ;
78
+ if (variableData != null ) {
79
+ data = Bytes .get (variableData .getSubsection (variableOffset + 46 ,
80
+ nameLength + extraLength + commentLength ));
81
+ dataOffset = 0 ;
82
+ }
83
+ this .name = new AsciiBytes (data , dataOffset , (int ) nameLength );
84
+ this .extra = NO_EXTRA ;
85
+ this .comment = NO_COMMENT ;
86
+ if (extraLength > 0 ) {
87
+ this .extra = new byte [(int ) extraLength ];
88
+ System .arraycopy (data , (int ) (dataOffset + nameLength ), this .extra , 0 ,
89
+ this .extra .length );
90
+ }
91
+ if (commentLength > 0 ) {
92
+ this .comment = new AsciiBytes (data ,
93
+ (int ) (dataOffset + nameLength + extraLength ), (int ) commentLength );
94
+ }
59
95
}
60
96
61
97
public AsciiBytes getName () {
@@ -73,12 +109,12 @@ public boolean isDirectory() {
73
109
74
110
@ Override
75
111
public int getMethod () {
76
- return (int ) Bytes .littleEndianValue (this .header , 10 , 2 );
112
+ return (int ) Bytes .littleEndianValue (this .header , this . headerOffset + 10 , 2 );
77
113
}
78
114
79
115
public long getTime () {
80
- long date = Bytes .littleEndianValue (this .header , 14 , 2 );
81
- long time = Bytes .littleEndianValue (this .header , 12 , 2 );
116
+ long date = Bytes .littleEndianValue (this .header , this . headerOffset + 14 , 2 );
117
+ long time = Bytes .littleEndianValue (this .header , this . headerOffset + 12 , 2 );
82
118
return decodeMsDosFormatDateTime (date , time ).getTimeInMillis ();
83
119
}
84
120
@@ -101,17 +137,17 @@ private Calendar decodeMsDosFormatDateTime(long date, long time) {
101
137
}
102
138
103
139
public long getCrc () {
104
- return Bytes .littleEndianValue (this .header , 16 , 4 );
140
+ return Bytes .littleEndianValue (this .header , this . headerOffset + 16 , 4 );
105
141
}
106
142
107
143
@ Override
108
144
public long getCompressedSize () {
109
- return Bytes .littleEndianValue (this .header , 20 , 4 );
145
+ return Bytes .littleEndianValue (this .header , this . headerOffset + 20 , 4 );
110
146
}
111
147
112
148
@ Override
113
149
public long getSize () {
114
- return Bytes .littleEndianValue (this .header , 24 , 4 );
150
+ return Bytes .littleEndianValue (this .header , this . headerOffset + 24 , 4 );
115
151
}
116
152
117
153
public byte [] getExtra () {
@@ -127,32 +163,20 @@ public long getLocalHeaderOffset() {
127
163
return this .localHeaderOffset ;
128
164
}
129
165
130
- public static CentralDirectoryFileHeader fromRandomAccessData (RandomAccessData data ,
131
- int offset ) throws IOException {
132
- InputStream inputStream = data .getSubsection (offset , data .getSize () - offset )
133
- .getInputStream (ResourceAccess .ONCE );
134
- try {
135
- return fromInputStream (inputStream );
136
- }
137
- finally {
138
- inputStream .close ();
139
- }
166
+ @ Override
167
+ public CentralDirectoryFileHeader clone () {
168
+ byte [] header = new byte [46 ];
169
+ System .arraycopy (this .header , this .headerOffset , header , 0 , header .length );
170
+ return new CentralDirectoryFileHeader (header , 0 , this .name , header , this .comment ,
171
+ this .localHeaderOffset );
140
172
}
141
173
142
- /**
143
- * Create a new {@link CentralDirectoryFileHeader} instance from the specified input
144
- * stream.
145
- * @param inputStream the input stream to load data from
146
- * @return a {@link CentralDirectoryFileHeader} or {@code null}
147
- * @throws IOException in case of I/O errors
148
- */
149
- static CentralDirectoryFileHeader fromInputStream (InputStream inputStream )
150
- throws IOException {
151
- byte [] header = new byte [46 ];
152
- if (!Bytes .fill (inputStream , header )) {
153
- return null ;
154
- }
155
- return new CentralDirectoryFileHeader (header , inputStream );
174
+ public static CentralDirectoryFileHeader fromRandomAccessData (RandomAccessData data ,
175
+ int offset ) throws IOException {
176
+ CentralDirectoryFileHeader fileHeader = new CentralDirectoryFileHeader ();
177
+ byte [] bytes = Bytes .get (data .getSubsection (offset , 46 ));
178
+ fileHeader .load (bytes , 0 , data , offset );
179
+ return fileHeader ;
156
180
}
157
181
158
182
}
0 commit comments