Line data Source code
1 : // Copyright (C) 2009 The Android Open Source Project 2 : // 3 : // Licensed under the Apache License, Version 2.0 (the "License"); 4 : // you may not use this file except in compliance with the License. 5 : // You may obtain a copy of the License at 6 : // 7 : // http://www.apache.org/licenses/LICENSE-2.0 8 : // 9 : // Unless required by applicable law or agreed to in writing, software 10 : // distributed under the License is distributed on an "AS IS" BASIS, 11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : // See the License for the specific language governing permissions and 13 : // limitations under the License. 14 : 15 : package com.google.gerrit.common; 16 : 17 : import com.google.common.collect.Sets; 18 : import java.io.IOException; 19 : import java.io.InputStream; 20 : import java.io.OutputStream; 21 : import java.lang.reflect.InvocationTargetException; 22 : import java.lang.reflect.Method; 23 : import java.net.MalformedURLException; 24 : import java.net.URL; 25 : import java.net.URLClassLoader; 26 : import java.nio.file.Path; 27 : import java.util.Arrays; 28 : import java.util.Collection; 29 : import java.util.Collections; 30 : import java.util.Set; 31 : 32 : public final class IoUtil { 33 : public static void copyWithThread(InputStream src, OutputStream dst) { 34 0 : new Thread("IoUtil-Copy") { 35 : // We cannot propagate the exception since this code is running in a background thread. 36 : // Printing the stacktrace is the best we can do. Hence ignoring the exception after printing 37 : // the stacktrace is OK and it's fine to suppress the warning for the CatchAndPrintStackTrace 38 : // bug pattern here. 39 : @SuppressWarnings("CatchAndPrintStackTrace") 40 : @Override 41 : public void run() { 42 : try { 43 0 : copyIo(); 44 0 : } catch (IOException e) { 45 0 : e.printStackTrace(); 46 0 : } 47 0 : } 48 : 49 : private void copyIo() throws IOException { 50 : try { 51 0 : final byte[] buf = new byte[256]; 52 : int n; 53 0 : while (0 < (n = src.read(buf))) { 54 0 : dst.write(buf, 0, n); 55 : } 56 : } finally { 57 : try { 58 0 : src.close(); 59 0 : } catch (IOException e2) { 60 : // Ignore 61 0 : } 62 : } 63 0 : } 64 0 : }.start(); 65 0 : } 66 : 67 : public static void loadJARs(Collection<Path> jars) { 68 138 : if (jars.isEmpty()) { 69 138 : return; 70 : } 71 : 72 0 : ClassLoader cl = IoUtil.class.getClassLoader(); 73 0 : if (!(cl instanceof URLClassLoader)) { 74 0 : throw noAddURL("Not loaded by URLClassLoader", null); 75 : } 76 : 77 : @SuppressWarnings("resource") // Leave open so classes can be loaded. 78 0 : URLClassLoader urlClassLoader = (URLClassLoader) cl; 79 : 80 : Method addURL; 81 : try { 82 0 : addURL = URLClassLoader.class.getDeclaredMethod("addURL", URL.class); 83 0 : addURL.setAccessible(true); 84 0 : } catch (SecurityException | NoSuchMethodException e) { 85 0 : throw noAddURL("Method addURL not available", e); 86 0 : } 87 : 88 0 : Set<URL> have = Sets.newHashSet(Arrays.asList(urlClassLoader.getURLs())); 89 0 : for (Path path : jars) { 90 : try { 91 0 : URL url = path.toUri().toURL(); 92 0 : if (have.add(url)) { 93 0 : addURL.invoke(cl, url); 94 : } 95 0 : } catch (MalformedURLException | IllegalArgumentException | IllegalAccessException e) { 96 0 : throw noAddURL("addURL " + path + " failed", e); 97 0 : } catch (InvocationTargetException e) { 98 0 : throw noAddURL("addURL " + path + " failed", e.getCause()); 99 0 : } 100 0 : } 101 0 : } 102 : 103 : public static void loadJARs(Path jar) { 104 0 : loadJARs(Collections.singleton(jar)); 105 0 : } 106 : 107 : private static UnsupportedOperationException noAddURL(String m, Throwable why) { 108 0 : String prefix = "Cannot extend classpath: "; 109 0 : return new UnsupportedOperationException(prefix + m, why); 110 : } 111 : 112 : private IoUtil() {} 113 : }