1 /*
2 * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.util.jar;
27
28 import java.io.DataOutputStream;
29 import java.io.FilterInputStream;
30 import java.io.IOException;
31 import java.io.InputStream;
32 import java.io.OutputStream;
33 import java.util.HashMap;
34 import java.util.Map;
35
36 import sun.nio.cs.UTF_8;
37 import sun.security.util.SecurityProperties;
38
39 /**
40 * The Manifest class is used to maintain Manifest entry names and their
41 * associated Attributes. There are main Manifest Attributes as well as
42 * per-entry Attributes. For information on the Manifest format, please
43 * see the
44 * <a href="{@docRoot}/../specs/jar/jar.html">
45 * Manifest format specification</a>.
46 *
47 * @author David Connelly
48 * @see Attributes
49 * @since 1.2
50 */
51 public class Manifest implements Cloneable {
52
213 dos.flush();
214 }
215
216 /**
217 * Adds line breaks to enforce a maximum of 72 bytes per line.
218 *
219 * @deprecation Replaced with {@link #println72}.
220 */
221 @Deprecated(since = "13")
222 static void make72Safe(StringBuffer line) {
223 int length = line.length();
224 int index = 72;
225 while (index < length) {
226 line.insert(index, "\r\n ");
227 index += 74; // + line width + line break ("\r\n")
228 length += 3; // + line break ("\r\n") and space
229 }
230 }
231
232 /**
233 * Writes {@code line} to {@code out} with line breaks and continuation
234 * spaces within the limits of 72 bytes of contents per line followed
235 * by a line break.
236 */
237 static void println72(OutputStream out, String line) throws IOException {
238 if (!line.isEmpty()) {
239 byte[] lineBytes = line.getBytes(UTF_8.INSTANCE);
240 int length = lineBytes.length;
241 // first line can hold one byte more than subsequent lines which
242 // start with a continuation line break space
243 out.write(lineBytes[0]);
244 int pos = 1;
245 while (length - pos > 71) {
246 out.write(lineBytes, pos, 71);
247 pos += 71;
248 println(out);
249 out.write(' ');
250 }
251 out.write(lineBytes, pos, length - pos);
252 }
253 println(out);
254 }
255
256 /**
257 * Writes a line break to {@code out}.
258 */
259 static void println(OutputStream out) throws IOException {
260 out.write('\r');
261 out.write('\n');
262 }
263
264 static String getErrorPosition(String filename, final int lineNumber) {
265 if (filename == null ||
266 !SecurityProperties.INCLUDE_JAR_NAME_IN_EXCEPTIONS) {
267 return "line " + lineNumber;
268 }
269 return "manifest of " + filename + ":" + lineNumber;
270 }
271
|
1 /*
2 * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.util.jar;
27
28 import java.io.DataOutputStream;
29 import java.io.FilterInputStream;
30 import java.io.IOException;
31 import java.io.InputStream;
32 import java.io.OutputStream;
33 import java.text.BreakIterator;
34 import java.util.HashMap;
35 import java.util.Map;
36
37 import sun.nio.cs.UTF_8;
38 import sun.security.util.SecurityProperties;
39
40 /**
41 * The Manifest class is used to maintain Manifest entry names and their
42 * associated Attributes. There are main Manifest Attributes as well as
43 * per-entry Attributes. For information on the Manifest format, please
44 * see the
45 * <a href="{@docRoot}/../specs/jar/jar.html">
46 * Manifest format specification</a>.
47 *
48 * @author David Connelly
49 * @see Attributes
50 * @since 1.2
51 */
52 public class Manifest implements Cloneable {
53
214 dos.flush();
215 }
216
217 /**
218 * Adds line breaks to enforce a maximum of 72 bytes per line.
219 *
220 * @deprecation Replaced with {@link #println72}.
221 */
222 @Deprecated(since = "13")
223 static void make72Safe(StringBuffer line) {
224 int length = line.length();
225 int index = 72;
226 while (index < length) {
227 line.insert(index, "\r\n ");
228 index += 74; // + line width + line break ("\r\n")
229 length += 3; // + line break ("\r\n") and space
230 }
231 }
232
233 /**
234 * Returns {@code true} if the passed byte as parameter {@code b}
235 * is not the first (or only) byte of a Unicode character encoded in UTF-8
236 * and {@code false} otherwise.
237 *
238 * @see <a href="https://tools.ietf.org/html/rfc3629#section-3">
239 * RFC 3629 - UTF-8, a transformation format of ISO 10646</a>
240 * @see StringCoding#isNotContinuation(int)
241 * @see sun.nio.cs.UTF_8.Decoder#isNotContinuation(int)
242 */
243 private static boolean isContinuation(byte b) {
244 return (b & 0xc0) == 0x80;
245 }
246
247 /**
248 * Writes {@code line} to {@code out} with line breaks and continuation
249 * spaces within the limits of 72 bytes of contents per line
250 * keeping byte sequences of characters encoded in UTF-8 together
251 * also if the same character is encoded with more than one byte or
252 * consists of a character sequence containing combining diacritical marks
253 * followed by a line break.
254 * <p>
255 * Combining diacritical marks may be separated from the associated base
256 * character or other combining diacritical marks of that base character
257 * by a continuation line break ("{@code \r\n }") if the whole sequence of
258 * base character and all the combining diacritical marks belonging to it
259 * exceed 71 bytes in their binary form encoded with UTF-8. This limit is
260 * only 71 bytes rather than 72 because continuation lines start with a
261 * space that uses the first byte of the 72 bytes each line can hold up to
262 * and the first line provides even less space for the value because it
263 * starts with the name.
264 */
265 static void println72(OutputStream out, String line) throws IOException {
266 int linePos = 0; // number of bytes already put out on current line
267 BreakIterator boundary = BreakIterator.getCharacterInstance();
268 boundary.setText(line);
269 int start = boundary.first(), end;
270 while ((end = boundary.next()) != BreakIterator.DONE) {
271 String character = line.substring(start, end);
272 start = end;
273 byte[] characterBytes = character.getBytes(UTF_8.INSTANCE);
274 int characterLength = characterBytes.length;
275 // Put out a break onto a new line if the character does not fit on
276 // the current line anymore but fits on a whole new line.
277 // In other words, if the current character does not fit on one
278 // whole line alone, fill the current line first before breaking
279 // inside of the character onto a new line.
280 if (linePos + characterLength > 72 && characterLength < 72) {
281 println(out);
282 out.write(' ');
283 linePos = 1;
284 }
285 int characterPos = 0; // number of bytes of current character
286 // already put out
287 while (linePos + characterLength - characterPos > 72) {
288 int nextBreakPos = 72 - linePos;
289 while (isContinuation(
290 characterBytes[characterPos + nextBreakPos])) {
291 nextBreakPos--;
292 }
293 out.write(characterBytes, characterPos, nextBreakPos);
294 characterPos += nextBreakPos;
295 println(out);
296 out.write(' ');
297 linePos = 1;
298 }
299 out.write(characterBytes,
300 characterPos, characterLength - characterPos);
301 linePos += characterLength - characterPos;
302 }
303 println(out);
304 }
305
306 /**
307 * Writes a line break to {@code out}.
308 */
309 static void println(OutputStream out) throws IOException {
310 out.write('\r');
311 out.write('\n');
312 }
313
314 static String getErrorPosition(String filename, final int lineNumber) {
315 if (filename == null ||
316 !SecurityProperties.INCLUDE_JAR_NAME_IN_EXCEPTIONS) {
317 return "line " + lineNumber;
318 }
319 return "manifest of " + filename + ":" + lineNumber;
320 }
321
|