• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*******************************************************************************
2  * Copyright (c) 2009, 2017 Mountainminds GmbH & Co. KG and Contributors
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  *    Evgeny Mandrikov - initial API and implementation
10  *
11  *******************************************************************************/
12 package org.jacoco.core.internal;
13 
14 import java.io.ByteArrayOutputStream;
15 import java.io.IOException;
16 import java.io.InputStream;
17 
18 import org.objectweb.asm.Opcodes;
19 
20 /**
21  * Patching for Java 9 classes, so that ASM can read them.
22  */
23 public final class Java9Support {
24 
25 	/**
26 	 * Version of the Java 9 class file format.
27 	 */
28 	public static final int V1_9 = Opcodes.V1_8 + 1;
29 
Java9Support()30 	private Java9Support() {
31 	}
32 
33 	/**
34 	 * Reads all bytes from an input stream into a byte array.
35 	 *
36 	 * @param is
37 	 *             the input stream to read from
38 	 * @return a byte array containing all the bytes from the stream
39 	 * @throws IOException
40 	 *             if an I/O error occurs
41 	 */
readFully(final InputStream is)42 	public static byte[] readFully(final InputStream is)
43 			throws IOException {
44 		if (is == null) {
45 			throw new IllegalArgumentException();
46 		}
47 		final byte[] buf = new byte[1024];
48 		final ByteArrayOutputStream out = new ByteArrayOutputStream();
49 		while (true) {
50 			int r = is.read(buf);
51 			if (r == -1) {
52 				break;
53 			}
54 			out.write(buf, 0, r);
55 		}
56 		return out.toByteArray();
57 	}
58 
putShort(byte[] b, int index, int s)59 	private static void putShort(byte[] b, int index, int s) {
60 		b[index] = (byte) (s >>> 8);
61 		b[index + 1] = (byte) s;
62 	}
63 
readShort(byte[] b, int index)64 	private static short readShort(byte[] b, int index) {
65 		return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF));
66 	}
67 
68 	/**
69 	 * Determines whether class definition contains {@link #V1_9} version.
70 	 *
71 	 * @param buffer
72 	 *             definition of the class
73 	 * @return <code>true</code> if class definition contains Java 9 version
74 	 */
isPatchRequired(byte[] buffer)75 	public static boolean isPatchRequired(byte[] buffer) {
76 		return readShort(buffer, 6) == V1_9;
77 	}
78 
79 	/**
80 	 * Returns new definition of class with version {@link Opcodes#V1_8},
81 	 * if it has version {@link #V1_9}.
82 	 *
83 	 * @param buffer
84 	 *             definition of the class
85 	 * @return new definition of the class
86 	 */
downgradeIfRequired(byte[] buffer)87 	public static byte[] downgradeIfRequired(byte[] buffer) {
88 		return isPatchRequired(buffer) ? downgrade(buffer) : buffer;
89 	}
90 
91 	/**
92 	 * Replaces version in the definition of class on {@link Opcodes#V1_8}.
93 	 *
94 	 * @param b
95 	 *             definition of the class
96 	 * @return new definition of the class
97 	 */
downgrade(byte[] b)98 	public static byte[] downgrade(byte[] b) {
99 		byte[] result = new byte[b.length];
100 		System.arraycopy(b, 0, result, 0, b.length);
101 		putShort(result, 6, Opcodes.V1_8);
102 		return result;
103 	}
104 
105 	/**
106 	 * Replaces version in the definition of class on {@link #V1_9}.
107 	 *
108 	 * @param b
109 	 *             definition of the class
110 	 */
upgrade(byte[] b)111 	public static void upgrade(byte[] b) {
112 		putShort(b, 6, V1_9);
113 	}
114 
115 }
116