1 package org.robolectric.util; 2 3 import java.io.File; 4 import java.io.IOException; 5 import java.io.InputStream; 6 import java.io.OutputStream; 7 import java.net.URISyntaxException; 8 import java.net.URL; 9 import java.nio.file.Path; 10 import java.nio.file.Paths; 11 12 /** Generic collection of utility methods. */ 13 public class Util { 14 15 /** 16 * Returns the Java version as an int value. 17 * 18 * @return the Java version as an int value (8, 9, etc.) 19 */ getJavaVersion()20 public static int getJavaVersion() { 21 String version = System.getProperty("java.version"); 22 assert version != null; 23 if (version.startsWith("1.")) { 24 version = version.substring(2); 25 } 26 // Allow these formats: 27 // 1.8.0_72-ea 28 // 9-ea 29 // 9 30 // 9.0.1 31 int dotPos = version.indexOf('.'); 32 int dashPos = version.indexOf('-'); 33 return Integer.parseInt( 34 version.substring(0, dotPos > -1 ? dotPos : dashPos > -1 ? dashPos : version.length())); 35 } 36 37 @SuppressWarnings({"AndroidJdkLibsChecker", "NewApi"}) // not relevant, always runs on JVM copy(InputStream in, OutputStream out)38 public static void copy(InputStream in, OutputStream out) throws IOException { 39 try { 40 in.transferTo(out); 41 } finally { 42 in.close(); 43 } 44 } 45 46 /** 47 * This method consumes an input stream and returns its content, and closes it. 48 * 49 * @param is The input stream to read from. 50 * @return The bytes read from the stream. 51 * @throws IOException Error reading from stream. 52 */ 53 @SuppressWarnings({"AndroidJdkLibsChecker", "NewApi"}) // not relevant, always runs on JVM readBytes(InputStream is)54 public static byte[] readBytes(InputStream is) throws IOException { 55 try { 56 return is.readAllBytes(); 57 } finally { 58 is.close(); 59 } 60 } 61 reverse(T[] array)62 public static <T> T[] reverse(T[] array) { 63 for (int i = 0; i < array.length / 2; i++) { 64 int destI = array.length - i - 1; 65 T o = array[destI]; 66 array[destI] = array[i]; 67 array[i] = o; 68 } 69 return array; 70 } 71 file(String... pathParts)72 public static File file(String... pathParts) { 73 return file(new File("."), pathParts); 74 } 75 file(File f, String... pathParts)76 public static File file(File f, String... pathParts) { 77 for (String pathPart : pathParts) { 78 f = new File(f, pathPart); 79 } 80 81 String dotSlash = "." + File.separator; 82 if (f.getPath().startsWith(dotSlash)) { 83 f = new File(f.getPath().substring(dotSlash.length())); 84 } 85 86 return f; 87 } 88 89 @SuppressWarnings("NewApi") pathFrom(URL localArtifactUrl)90 public static Path pathFrom(URL localArtifactUrl) { 91 try { 92 return Paths.get(localArtifactUrl.toURI()); 93 } catch (URISyntaxException e) { 94 throw new RuntimeException("huh? " + localArtifactUrl, e); 95 } 96 } 97 parseInt(String valueFor)98 public static int parseInt(String valueFor) { 99 if (valueFor.startsWith("0x")) { 100 return Integer.parseInt(valueFor.substring(2), 16); 101 } else { 102 return Integer.parseInt(valueFor, 10); 103 } 104 } 105 106 /** 107 * Re-throw {@code t} (even if it's a checked exception) without requiring a {@code throws} 108 * declaration. 109 * 110 * <p>This function declares a return type of {@link RuntimeException} but will never actually 111 * return a value. This allows you to use it with a {@code throw} statement to convince the 112 * compiler that the current branch will not complete. 113 * 114 * <pre>{@code 115 * throw Util.sneakyThrow(new IOException()); 116 * }</pre> 117 * 118 * <p>Adapted from https://www.mail-archive.com/[email protected]/msg05984.html 119 */ 120 @SuppressWarnings("unchecked") sneakyThrow(Throwable t)121 public static <T extends Throwable> RuntimeException sneakyThrow(Throwable t) throws T { 122 throw (T) t; 123 } 124 } 125