1 /* 2 * $Id$ 3 * 4 * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. 5 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6 * 7 * This code is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License version 2 only, as 9 * published by the Free Software Foundation. Oracle designates this 10 * particular file as subject to the "Classpath" exception as provided 11 * by Oracle in the LICENSE file that accompanied this code. 12 * 13 * This code is distributed in the hope that it will be useful, but WITHOUT 14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16 * version 2 for more details (a copy is included in the LICENSE file that 17 * accompanied this code). 18 * 19 * You should have received a copy of the GNU General Public License version 20 * 2 along with this work; if not, write to the Free Software Foundation, 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 22 * 23 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 24 * or visit www.oracle.com if you need additional information or have any 25 * questions. 26 */ 27 package com.sun.javatest.tool; 28 29 import java.io.BufferedReader; 30 import java.io.File; 31 import java.io.IOException; 32 import java.io.InputStreamReader; 33 import java.io.PrintStream; 34 import java.lang.reflect.Constructor; 35 import java.lang.reflect.InvocationTargetException; 36 import java.net.MalformedURLException; 37 import java.net.URL; 38 import java.net.URLClassLoader; 39 import java.util.Enumeration; 40 import java.util.HashSet; 41 import java.util.Set; 42 43 import com.sun.javatest.ResourceLoader; 44 import com.sun.javatest.util.DynamicArray; 45 import com.sun.javatest.util.I18NResourceBundle; 46 import com.sun.javatest.util.StringArray; 47 48 class ManagerLoader 49 { 50 ManagerLoader(Class managerClass, PrintStream log) { 51 setManagerClass(managerClass); 52 setLog(log); 53 } 54 55 void setManagerClass(Class managerClass) { 56 this.managerClass = managerClass; 57 } 58 59 void setManagerConstructorArgs(Class[] argTypes, Object[] args) { 60 constrArgTypes = argTypes; 61 constrArgs = args; 62 } 63 64 void setLog(PrintStream log) { 65 this.log = log; 66 } 67 68 Set<Object> loadManagers(String resourceName) 69 throws IOException 70 { 71 72 Enumeration e = ResourceLoader.getResources(resourceName, getClass()); 73 Set<Object> mgrs = new HashSet<>(); 74 URLClassLoader altLoader = null; 75 76 while (e.hasMoreElements()) { 77 URL entry = (URL)(e.nextElement()); 78 try { 79 BufferedReader in = new BufferedReader(new InputStreamReader(entry.openStream())); 80 String line; 81 while ((line = in.readLine()) != null) { 82 line = line.trim(); 83 if (line.length() == 0) { 84 continue; 85 } else if (line.startsWith("#")) { 86 line = line.substring(1).trim(); 87 if (line.startsWith("classpath=")) { 88 line = line.substring(10).trim(); 89 altLoader = getSecondaryLoader(line); 90 // note that only the last classpath line would be used 91 } 92 93 continue; 94 } // elseif 95 96 try { 97 Object mgr = newInstance(this.getClass().getClassLoader(), 98 line, entry); 99 if (mgr == null && altLoader != null) { 100 // attempt to load from the alternate class loader 101 mgr = newInstance(altLoader, line, entry); 102 } 103 104 if (mgr != null) { 105 mgrs.add(mgr); 106 } else { 107 if (log != null) { 108 writeI18N("ml.cantFindClass", new Object[]{line, entry}); 109 } 110 } 111 } 112 catch (IllegalAccessException ex) { 113 if (log != null) { 114 writeI18N("ml.cantAccessClass", new Object[] { line, entry } ); 115 } 116 } 117 catch (InstantiationException ex) { 118 if (log != null) { 119 writeI18N("ml.cantCreateClass", new Object[] { line, entry } ); 120 } 121 } 122 catch (NoSuchMethodException ex) { 123 if (log != null) { 124 writeI18N("ml.cantFindConstr", new Object[] { line, entry } ); 125 } 126 } 127 } // while 128 in.close(); 129 } 130 catch (IOException ex) { 131 if (log != null) 132 writeI18N("ml.cantRead", new Object[] { entry, ex }); 133 } 134 } 135 return mgrs; 136 } 137 138 /** 139 * Throws the declared exceptions because it seems that the class was found 140 * but couldn't be used. Not being able to find the class is not a problem, 141 * this is handled in the code in other ways. 142 * @param cl Class loader to use. 143 * @param className Class to load. 144 * @param specfile File which specified the classname to be loaded - used 145 * for error message purposes. 146 * @return An instance of the requested class, null if not found. Or if the 147 * object created is not a manager subclass. 148 * @throws InstantiationException 149 * @throws NoSuchMethodException 150 * @throws IllegalAccessException 151 */ 152 private Object newInstance(ClassLoader cl, String className, URL specfile) 153 throws InstantiationException, NoSuchMethodException, IllegalAccessException { 154 if (cl == null) { 155 return null; 156 } 157 158 try { 159 Class c = Class.forName(className, true, cl); 160 Object mgr = newInstance(c); 161 if (managerClass.isInstance(mgr)) { 162 return mgr; 163 } else { 164 if (log != null) { 165 writeI18N("ml.notSubtype", new Object[]{className, 166 managerClass.getName(), specfile}); 167 } 168 } 169 } catch (ClassNotFoundException ex) { 170 } 171 172 return null; 173 } 174 175 private Object newInstance(Class<?> c) 176 throws IllegalAccessException, InstantiationException, NoSuchMethodException 177 { 178 if (constrArgTypes == null || constrArgTypes.length == 0) { 179 return c.newInstance(); 180 } 181 182 try { 183 Constructor constr = c.getConstructor(constrArgTypes); 184 return constr.newInstance(constrArgs); 185 } 186 catch (InvocationTargetException e) { 187 Throwable t = e.getTargetException(); 188 if (t instanceof RuntimeException) { 189 throw ((RuntimeException) t); 190 } 191 else if (t instanceof Error) { 192 throw ((Error) t); 193 } 194 else { 195 throw new Error(e); 196 } 197 } 198 } 199 200 private URLClassLoader getSecondaryLoader(String paths) { 201 String[] cps = StringArray.splitList(paths, ":"); 202 203 if (cps == null || cps.length == 0) { 204 return null; 205 } 206 207 URL[] urls = new URL[0]; 208 boolean someCPok = false; 209 for (String s : cps) { 210 URL u = ResourceLoader.getExtUrl(new File(s)); 211 212 if (u != null) { 213 urls = DynamicArray.append(urls, u); 214 someCPok = true; 215 } 216 } // for 217 218 // none of the input classpath can be used 219 if (!someCPok || urls == null || urls.length == 0) { 220 if (log != null) { 221 log.println("Unable to create valid paths from any of the custom tool classpath items."); 222 } 223 return null; 224 } 225 226 // create CL 227 try { 228 URLClassLoader cl = new URLClassLoader(urls); 229 return cl; 230 } catch (SecurityException e) { 231 if (log != null) { 232 log.println("Unable to create custom class loader to load tool managers:"); 233 e.printStackTrace(log); 234 } 235 return null; 236 } // catch 237 } 238 239 private void writeI18N(String key, Object[] args) { 240 log.println(i18n.getString(key, args)); 241 } 242 243 private Class<?> managerClass; 244 private Constructor constr; 245 private Class[] constrArgTypes; 246 private Object[] constrArgs; 247 private PrintStream log; 248 249 private static I18NResourceBundle i18n = I18NResourceBundle.getBundleForClass(ManagerLoader.class); 250 }